Skip to main content

Play+ Linting Guide: playlint

Introduction

In the Play+ ecosystem, we believe the codebase is a user interface for developers. It must be as intuitive, clean, and predictable as the products we ship. This guide is based on the concept of codified quality standards.

Our linting setup is essential for creating a frictionless and efficient development experience by automatically enforcing a consistent style and flagging potential issues early. This directly supports our core design pillars: making our codebase Distinct through uniform style, Intuitive by clarifying intent and reducing cognitive load, and Inclusive by baking in accessibility checks from the first line of code.

Package Info

The Play+ linting configuration is provided as a development dependency and is pre-installed in all Golden Path starter kits.

DescriptionPackage / Path
Golden Path (Recommended)Pre-installed as a devDependency
Uplift Pathnpm install --save-dev @playplus/eslint-config

Folder Reference

The linting setup relies on a few key configuration files at the root of your project.

File / DirectoryPurpose & Guidelines
.eslintrc.jsThe main ESLint configuration file. It extends the base @playplus/eslint-config.
.prettierrcConfiguration file for Prettier, ensuring consistent code formatting.
package.jsonDefines the playlint script and lists the dev dependencies.
reports/The git-ignored directory where automated linting reports are saved.

Helper - Pillars Alignment

Our automated linting strategy is a direct implementation of our core design pillars, applied to the code itself.

PillarHow This Helper Aligns
DistinctEnforces a uniform coding style and naming convention, creating a recognizable brand identity at the code level.
IntuitiveCodifies best practices to reduce cognitive load, making code easier to read, reason about, and maintain.
InclusiveIntegrates accessibility (a11y) checks directly into the linter, ensuring products are built for everyone from the start.

Helper Overview

Unlike other helpers that provide runtime APIs, the Play+ linting setup is a zero-configuration toolchain. It's delivered as an ESLint configuration package (@playplus/eslint-config) and a set of pre-configured scripts. Its purpose is to abstract the plumbing of setting up and maintaining a modern linting environment.

It automates quality control across the development lifecycle:

  • During Development: Provides real-time feedback in your IDE.
  • On Commit: A pre-commit hook automatically checks and fixes staged files, blocking critical issues.
  • In Continuous Integration: A playlint script runs on every pull request, failing the build if errors are present to protect the main branch.

This system ensures that every developer on every team adheres to the same high standards of quality, security, and accessibility without needing to configure anything themselves.

Config Options

While the setup is designed to be zero-config, you can override specific rules in your project's .eslintrc.js file. This should be done sparingly and with team consensus.

Config FileActionExample
.eslintrc.jsOverride a rulerules: { 'no-console': ['off', { allow: ['warn', 'error'] }] }
.eslintrc.jsExtend configurationextends: ['@playplus/eslint-config', 'plugin:my-plugin/recommended']

Example .eslintrc.js:

// .eslintrc.js
module.exports = {
extends: ['@playplus/eslint-config'],
rules: {
// Overrides the default rule to allow console.warn and console.error
'no-console': ['error', { allow: ['warn', 'error'] }],
},
};

Key Scripts & Commands

The functionality is exposed through npm scripts defined in your package.json.

Script NameWhat It DoesDefault Command
playlintRuns the ESLint checker across all relevant source files in the project.eslint .
playlint:reportRuns the linter and generates a machine-readable JSON report in the reports/ directory.eslint . --format json --output-file reports/lint-report.json

Usage Examples

React & Angular: Automated Enforcement

For both frameworks, the Golden Path provides complete automation. There is nothing to set up.

  1. In your IDE: With the recommended extensions (ESLint/Prettier), you get real-time feedback as you type.
  2. When you commit: A pre-commit hook (via Husky) automatically lints your changes.
  3. When you create a Pull Request: A GitHub Action runs npm run playlint, ensuring no errors can be merged.

VS Code IDE Setup

To get the best real-time experience, create a .vscode/settings.json file with the following content:

{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"editor.defaultFormatter": "esbenp.prettier-vscode"
}

Additional Info

Why We Built This

Configuring a modern linting toolchain is complex. It involves selecting and integrating multiple tools (ESLint, Prettier), plugins (for React, Angular, a11y, security), and defining hundreds of rules. Without a centralized solution, each team would waste time on setup and debates, leading to inconsistencies across projects.

The @playplus/eslint-config package solves this by providing a single, opinionated, and production-ready configuration. It eliminates boilerplate and configuration drift, ensuring every project starts with and maintains the same high-quality bar.

Best Practices

  • Trust the Automation: Let the pre-commit hooks and CI checks do their job.
  • Use Disables Sparingly: Only use // eslint-disable-next-line for true edge cases and always add a comment explaining why it's necessary.
  • Integrate Your IDE: A properly configured IDE gives you the fastest feedback loop.
  • Review Reports: Periodically check the generated lint-report.json to identify recurring patterns or areas for team-wide improvement.

Developer Checklist

  • Have I installed the recommended ESLint and Prettier extensions for my IDE?
  • Is my IDE configured for format-on-save and fix-on-save?
  • When I need to disable a rule, have I added a clear, explanatory comment?
  • Am I letting the CI/CD pipeline validate my code quality before merging?

Linting Standards & Rule Coverage

The @playplus/eslint-config package enforces a comprehensive set of rules by default. The following standards are automatically applied to all projects to ensure consistency, quality, and safety. While these rules can be toggled by developers in their local configuration, it is not advised as it creates divergence from the Play+ standard.

Code Quality

Key (Rule)Default ValueDescription
prefer-consterrorRequires const declarations for variables that are never reassigned.
no-varerrorDisallows the use of var in favor of let and const.
prefer-arrow-callbackerrorEnforces the use of arrow functions for callbacks.
no-unused-varswarnFlags variables that are declared but never used.
complexity['error', 10]Limits cyclomatic complexity to prevent overly complex functions.
import/ordererrorEnforces a consistent and logical order for import statements.
eqeqeqerrorRequires the use of strict equality operators === and !==.
prefer-templateerrorEnforces the use of template literals instead of string concatenation.
no-throw-literalerrorRestricts what can be thrown as an exception, requiring Error objects.
no-evalerrorDisallows the use of the eval() function to prevent security risks.
max-depth['warn', 4]Warns when code is nested too deeply.
unused-imports/no-unused-importswarnFlags unused import statements that can be safely removed.

Accessibility

Key (Rule)Default ValueDescription
jsx-a11y/alt-texterrorEnforces that all <img> elements have meaningful alt text.
jsx-a11y/label-has-associated-controlerrorRequires that every form label is associated with a form control.
jsx-a11y/aria-propserrorEnforces that only valid ARIA props are used.
jsx-a11y/click-events-have-key-eventserrorRequires a keyboard event handler for elements with a click event.
jsx-a11y/no-redundant-roleserrorPrevents the use of ARIA roles on elements that have implicit roles.

Security

Key (Rule)Default ValueDescription
react/no-dangerwarnWarns against the use of dangerouslySetInnerHTML.
react/jsx-no-target-blankerrorEnforces rel="noreferrer" on links with target="_blank".
security/detect-unsafe-regexwarnDetects regular expressions that are susceptible to ReDoS attacks.
security/detect-child-processwarnFlags the use of child_process which can be a security risk.

Framework: React

Key (Rule)Default ValueDescription
react-hooks/rules-of-hookserrorEnforces the Rules of Hooks to prevent common mistakes.
react-hooks/exhaustive-depswarnVerifies dependency arrays in hooks like useEffect and useCallback.
react/no-direct-mutation-stateerrorPrevents direct mutation of this.state; setState must be used.
react/jsx-keyerrorRequires a unique key prop for elements in an array or iterator.

Framework: Angular

Key (Rule)Default ValueDescription
@angular-eslint/component-selectorerrorEnforces a consistent prefix for component selectors (e.g., app-).
@angular-eslint/no-empty-lifecycle-methodwarnFlags empty lifecycle methods that can be removed.
@angular-eslint/template/accessibility-alt-texterrorEnforces alt text on <img> elements inside Angular templates.

Formatting

Key (Rule)Default ValueDescription
prettier/prettiererrorRuns Prettier as an ESLint rule and reports differences as errors.