{"id":16504536,"url":"https://github.com/devstein/js-styleguide","last_synced_at":"2026-02-24T01:35:02.285Z","repository":{"id":98519194,"uuid":"176353835","full_name":"devstein/js-styleguide","owner":"devstein","description":"Personal JS Style Guide ","archived":false,"fork":false,"pushed_at":"2019-03-18T19:18:09.000Z","size":4,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-02T00:51:19.475Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devstein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-18T19:14:55.000Z","updated_at":"2020-02-07T17:06:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"c2ea3113-bdd1-42f2-a4d6-d47bd76bf381","html_url":"https://github.com/devstein/js-styleguide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/devstein/js-styleguide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstein%2Fjs-styleguide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstein%2Fjs-styleguide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstein%2Fjs-styleguide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstein%2Fjs-styleguide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devstein","download_url":"https://codeload.github.com/devstein/js-styleguide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstein%2Fjs-styleguide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29766805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T01:28:30.166Z","status":"ssl_error","status_checked_at":"2026-02-24T01:28:27.518Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T15:03:46.850Z","updated_at":"2026-02-24T01:35:02.263Z","avatar_url":"https://github.com/devstein.png","language":null,"readme":"# JS Style Guide\n\n## Code for Others \n\n- Your code is going to be read many, many, many other developers. Always be conscious and thoughtful about making their jobs as easy as possible.  \n- Code is craft. Be proud of the code your write. If you aren't, get feedback and ideas from others!  \n\n## Type System\n- All files must be typed \n- Use Typescript or [flow](https://flow.org/en/)\n\n## Follow Functional Paradigms\n\n- Functions should be pure and maintain [referential transparency](https://www.sitepoint.com/what-is-referential-transparency/)\n- Functions should not have unnecessary side effects\n- Functions must be unit testable\n- [Leverage ES6 syntax](https://medium.com/dailyjs/functional-js-with-es6-recursive-patterns-b7d0813ef9e3) to make writing functional JS easier\n- If want to use `.forEach`, then check [lodash](https://lodash.com/docs/4.17.11) for a more functional solution\n\n## Avoid Mutation at All Costs!\n\n- **Never** user `var` and **avoid** using `let` unless strictly needed.\n- If you find yourself using `let`, check the following:\n  1. Can I use a `ternary operator` for assignment?\n     ```js\n     const conditionalVariable = Boolean(otherVariable)\n       ? 'Condition true'\n       : 'Condition false';\n     ```\n  2. Can I extract this conditional logic into a helper function?\n     ```js\n     const multipleConditionsHelper = someValue =\u003e {\n       switch (someValue) {\n         case 'A':\n           return 'Value A';\n         case 'B':\n           return 'Value B';\n         default:\n           return 'Value C';\n       }\n     };\n\n     // further down in the file\n     const otherFunction = otherValue =\u003e {\n       const conditionalValue = multipleConditionsHelper(otherValue);\n     };\n     ```\n- Never do `someObject.foo = 'a'`\n    ```js\n    // BAD\n    const someObject = { bar: 'b' };\n    someObject.foo = 'a';\n\n    // GOOD\n    const someObject = { bar: 'b' };\n    const newObject = { ...someObject, foo: 'a' };\n\n    // ALSO GOOD\n    const someObject = {\n      bar: 'b',\n      foo: booleanValue ? 'a' : 'c',\n    };\n\n    // ALSO GOOD\n    const someObject = {\n      bar: 'b',\n      ...(booleanValue ? { foo: 'a' } : {}),\n    };\n    ```\n- If you are desparate for mutation, use [immer](https://github.com/mweststrate/immer). Immer is also great for simplifying [redux reducers](https://github.com/reduxjs/react-redux)!\n\n## Variable Naming\n\n- Variables and functions must be `camelCased` or uppercased `SNAKE_CASE` for global constants\n- Never use lowercase `snake_case`\n\n  ```js\n  // GOOD\n  const someFunction = () =\u003e {};\n  const someVariable = [];\n  const SOME_CONSTANT = 1337;\n\n  // BAD\n  const bad_variable_name = {};\n  ```\n\n- Variable names should signify its purpose\n  ```js\n  // GOOD\n  const nameList = ['Devin', 'Joe', 'Josh'];\n  // BAD\n  const list = ['Devin', 'Joe', 'Josh'];\n  ```\n- No magic numbers. Use constants for numbers.\n  ```js\n  // GOOD\n  const POLL_RATE = 15 * 1000;\n\n  const pollIntervalId = setInterval(() =\u003e {\n    console.log('poll');\n  }, POLL_RATE);\n\n  // BAD\n  const pollIntervalId = setInterval(() =\u003e {\n    console.log('poll');\n  }, 15 * 1000);\n  ```\n\n## Follow DRY Principles\n\n- If you find yourself duplicating logic extract, it into a utility function\n- If you repeat logic twice it can be OK, but duplicating logic three times is `rarely` acceptable\n- If you create a helper function to simplify the logic in a function, do not define it within the scope of the function!\n  ```js\n  // GOOD\n  const extractedComplicatedLogic = value =\u003e {\n    // do stuff\n  };\n\n  const importantFunction = currentValue =\u003e {\n    const updatedValue = extractedComplicatedLogic(currentValue);\n    // do more stuff\n  };\n\n  // BAD\n  const importantFunction = currentValue =\u003e {\n    const extractedComplicatedLogic = value =\u003e {\n      // do stuff\n    };\n\n    const updatedValue = extractedComplicatedLogic(currentValue);\n    // do more stuff\n  };\n  ```\n - Always keep abstractions in mind.\n   - How can I make this a repeatable pattern?\n   - How can I make a helper to make this abstract away boilerplate?\n   - If you think of an abstraction idea and don't have time, then leave a `TODO`!\n\n## Comments for Clarity\n\n- Comments should enhance the readability of your code\n- Always comment when understanding your code requires context beyond the scope of the file\n  - Explain the business logic that drove your decision\n  - Warn future developers that changing certain code will have unintended behaviors\n  - Emphasize the importance of a piece of code\n- If you don't love your variable name, its probably a bad variable name ☹️. But if you can't come up with a better one, leave a comment to explain the purpose of the variable!\n- Comment to help with future refactors\n- It's way harder to comment too much than it is to comment too little, so when in doubt, leave a comment!\n\n## Use Guards over Nested If/Else 💂‍♀️\n\n- Guards make functions more declarative and readable!\n- If you use an `else` statement, then check to see if you can re-write using a guard.\n  ```js\n  // BAD\n  const someFunction = someValue =\u003e {\n    if (someValue) {\n      return 'A';\n    } else {\n      return 'B';\n    }\n  };\n\n  // GOOD\n  // Much more readable!\n  const someFunction = someValue =\u003e {\n    if (!someValue) return 'B';\n\n    return 'A';\n  };\n  ```\n\n## Always Favor ES6 Module Imports and Exports. Avoid Closures and Classes.\n\n- Using `ES6` `import`/`export` makes it easier to unit test shared logic\n- Poorly maintained classes and closures lose the benefits of tree-shaking and dead code elimination\n- Avoiding classes and closures forces you to think functionally and reduces reliance on an internal state\n- There are use cases for classes and closures, but do not use unless strictly necessary.\n  ```js\n  // GOOD\n\n  // util.js\n  export const logger = value =\u003e console.log(`Logging ${value}`);\n\n  // other-file.js\n  import { logger } from './util.js';\n\n  // ------------------------------------\n\n  // GOOD\n  // logger.js\n  const logger = value =\u003e console.log(`Logging ${value}`);\n\n  export default logger;\n\n  // other-file.js\n  import logger from './logger';\n\n  // ------------------------------------\n  // BAD\n  // util.js\n  class Utilities {\n    logger = () =\u003e console.log(`Logging ${value}`);\n  }\n\n  export default Utilities;\n\n  // other-file.js\n  import Utilities from './util';\n  ```\n\n## Use Named Parameters (Objects) for Shared Functions\n\n- Use objects parameters for `import`-ed or shared functions\n- Order doesn't matter! The beauty of using objects for parameters, means future developers do not have to worry parameter ordering!\n\n  ```js\n  // GOOD\n\n  // helper.js\n  const helperFunction = ({ foo, bar }) =\u003e return `${foo}${bar}`;\n\n  // some-file.js\n  import { helperFunction } from \"../helpers\";\n\n  // YAY! Other developers do not need to worry about order, only parameter names.\n  const data = helperFunction({ bar: 'b', foo: 'a' });\n\n  // ------------------------------------------------------------------------\n  // BAD\n  const badHelper = (foo, bar) =\u003e return `${foo}${bar}`\n\n  // (BAD) Some developer accidentally messes up the order without knowing!\n  const localFoo = 'a';\n  const localBar = 'b';\n  const data = badHelper(localBar, localFoo);\n  ```\n  \n## ❤️ ES6 Arrow Functions , Destructuring, and Spreads\n\n- Always use arrow functions for consistencey\n  ```js\n  // GOOD\n  const someFunction = () =\u003e {};\n\n  // BAD\n  function someFunction() {}\n  ```\n- Destructuring for object and array parameters/variables\n- Destructure for variable assignment\n  ```js\n  // GOOD\n\n  // Ex. Simple destructing parameters\n  const functionWithObject = ({ foo, bar }) =\u003e {};\n  // Ex. Rename parameters\n  const functionWithObject = ({ foo: renamedFoo, bar: renamedBar }) =\u003e {};\n\n  const assignmentWithDestructing = person =\u003e {\n    const { firstName, lastName } = person;\n  };\n\n  // BAD\n  const assignmentWithoutDestructiong = person =\u003e {\n    const firstName = person.firstName;\n    const lastName = person.lastName;\n  };\n  ```\n- Use the spread operation `...` for merging and cloning objects and manipulating arrays!\n  ```js\n  const mergedObject = { ...oneObject, ...secondObject };\n  const clonedObject = { ...mergedObject };\n\n  const concatArrays = (arrayOne, arrayTwo) =\u003e [...arrayOne, ...arrayTwo];\n  const appendToArray = (array, item) =\u003e [...array, item];\n  const head = ([firstItem]) =\u003e firstItem;\n  const [firstItem, secondItem] = veryLongArray;\n  ```\n- Avoid creating uneccesary function\n  - Most importantly for `react` component props\n  - Use `_.flow` when you can to create a function that chains multiple functions\n\n## Git Guidelines\n\n- Name branches `username/short-branch-description`\n- Always have good [git hygiene](http://www.ericbmerritt.com/2011/09/21/commit-hygiene-and-git.html)\n- **Do not commit commented code**\n\n## ESLint\n\n```js\nmodule.exports = {\n  env: {\n    browser: true,\n    'jest/globals': true,\n  },\n  globals: {\n    browser: true,\n  },\n  extends: [\n    'airbnb', // tons of good defaults (very strict)\n    'plugin:flowtype/recommended', // optional for flow!\n    'plugin:jest/recommended',\n    'prettier', // disable all rules that conflict with prettier\n    'prettier/react', // disable all rules that conflict with prettier\n    'prettier/flowtype', // disable all rules that conflict with prettier\n  ],\n  // only include flow-type if we are using flow\n  plugins: ['flowtype', 'jest', 'react-hooks'],\n  rules: {\n    // START: Only if using flow\n    'react/prop-types': 'off',\n    'react/default-props-match-prop-types': 'off',\n    'react/no-multi-comp': 'off',\n    'react/require-default-props': 'off',\n\n    // require \"// flow\" at the top of all js files\n    'flowtype/require-valid-file-annotation': [\n      2,\n      'always',\n      {\n        annotationStyle: 'line',\n      },\n    ],\n    // STOP: Only if using flow\n\n    // Hooks :)\n    'react-hooks/rules-of-hooks': 'error',\n\n    'no-plusplus': 'off',\n    'import/prefer-default-export': 'off',\n\n    // airbnb rules that are too picky\n    'react/destructuring-assignment': 'off',\n\n    'lines-between-class-members': 'off', // too strict\n\n    // we import types from jest\n    'jest/no-jest-import': 'off',\n\n    'no-unused-vars': [\n      'error',\n      {\n        argsIgnorePattern: '^_',\n      },\n    ],\n  },\n};\n```\n\n## Prettier\n\n```json\n{\n  \"trailingComma\": \"all\",\n  \"singleQuote\": true,\n  \"semicolons\": true\n}\n```\n\n- Always format on save!\n\n## Stylelint\n\n- Assumes [Sass](https://sass-lang.com/guide)\n\n```json\n{\n  \"plugins\": [\"stylelint-scss\"],\n  \"extends\": \"stylelint-config-recommended\",\n  \"rules\": {\n    \"at-rule-no-unknown\": [\n      true,\n      {\n        \"ignoreAtRules\": [\"extend\", \"if\"]\n      }\n    ],\n    \"selector-pseudo-class-no-unknown\": [\n      true,\n      {\n        \"ignorePseudoClasses\": [\"global\"]\n      }\n    ]\n  }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevstein%2Fjs-styleguide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevstein%2Fjs-styleguide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevstein%2Fjs-styleguide/lists"}