Code Formatting Standards

Code formatting — indentation, spacing, line breaks, bracket placement, quote style — is one of the most debated topics in software development. Tabs or spaces? Semicolons or not? Opening braces on the same line or the next? These debates consume hours of code review time, create friction in teams, and distract from what actually matters: the logic, architecture, and correctness of the code. Automated formatting tools eliminate these debates entirely by applying a consistent style mechanically, freeing developers to focus on substance rather than style.

Why Consistent Formatting Matters

Reduced Cognitive Load

Reading code is a pattern-matching activity. When formatting is consistent, your brain develops expectations about where to find things: the opening brace is always in the same position, arguments are always indented the same way, imports are always grouped the same way. When formatting varies — one file uses tabs, another uses spaces; one function puts braces on the same line, the next puts them on a new line — your brain has to re-calibrate for each file, wasting mental energy on parsing style rather than understanding logic.

Research on code comprehension consistently shows that consistently formatted code is easier to read and understand, even when the specific formatting conventions differ from a reader's personal preference. The consistency matters more than the specific choices.

Cleaner Code Reviews

Without automated formatting, code reviews are polluted with style comments. "Please use single quotes here." "This line is too long." "Add a blank line before the return statement." These comments are necessary for consistency but tedious for both reviewer and author. They also bury substantive feedback about logic, security, and design under a pile of formatting nitpicks.

When formatting is automated, diffs contain only meaningful changes. A pull request that refactors a function shows only the logic changes, not the formatting changes. This makes reviews faster, more focused, and more effective at catching real issues.

Reduced Merge Conflicts

Inconsistent formatting creates unnecessary merge conflicts. If one developer reformats a file to use their preferred style while another makes a logical change to the same file, git cannot resolve the conflict automatically. With automated formatting, every developer's commits produce identically formatted code, minimizing style-only conflicts.

Onboarding Efficiency

New team members do not need to learn a style guide. They configure their editor to format on save (a one-time setup), and from that point forward, their code matches the project's conventions automatically. This removes a source of friction and self-consciousness for new contributors, who might otherwise worry about getting the "right" style before they feel confident with the codebase.

Prettier: Opinionated Multi-Language Formatting

Prettier is the most widely adopted automated code formatter. Its key design philosophy is to be opinionated: it makes most formatting decisions for you, offering very few configuration options. This is deliberate. By removing choices, Prettier removes debates. Your team does not argue about whether to use single or double quotes — you accept whatever Prettier defaults to (or pick one option and move on).

Prettier supports a wide range of languages and file formats:

  • JavaScript and TypeScript
  • HTML, CSS, SCSS, and Less
  • JSON and YAML
  • Markdown
  • GraphQL
  • PHP (via plugin)
  • Java (via plugin)

Prettier's configuration is intentionally minimal. The most common options are:

  • printWidth: Maximum line length before Prettier wraps. Default is 80.
  • tabWidth: Indentation width. Default is 2.
  • useTabs: Whether to use tabs instead of spaces. Default is false.
  • semi: Whether to add semicolons. Default is true.
  • singleQuote: Whether to use single quotes instead of double quotes. Default is false.
  • trailingComma: Whether to add trailing commas in multi-line structures. Default is "all" in Prettier 3.x.

A typical .prettierrc file is just a few lines:

{
  "printWidth": 100,
  "singleQuote": true,
  "trailingComma": "all"
}

That is all the configuration most teams need. Prettier handles everything else.

EditorConfig: Editor-Agnostic Settings

EditorConfig solves a different problem than Prettier. While Prettier reformats code after it is written, EditorConfig configures editors to use the right settings while code is being written. It sets indentation style and size, character encoding, line ending style, and whether to insert a final newline.

EditorConfig is supported natively or via plugins by virtually every code editor: VS Code, JetBrains IDEs, Sublime Text, Vim, Emacs, and more. A single .editorconfig file at the root of your repository ensures that every developer's editor produces consistent whitespace, regardless of their personal editor preferences.

A typical .editorconfig file:

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

EditorConfig and Prettier are complementary. EditorConfig ensures consistent settings across editors at the input stage, while Prettier reformats the output to guarantee consistency. Using both provides defense-in-depth: even if an editor does not have Prettier integrated, EditorConfig ensures the basics are correct.

Language-Specific Formatters

Some languages have official or de facto standard formatters that are part of the language toolchain. These formatters are particularly powerful because they understand the language's syntax deeply and produce idiomatic formatting that the entire language community follows.

Go: gofmt

gofmt is the original opinionated formatter and the inspiration for many that followed. It ships with the Go toolchain and is universally used in the Go community. There is no configuration — gofmt produces one canonical format for all Go code. This means every Go developer reads and writes code in the same style, regardless of which team, company, or open-source project they are working on. The entire "tabs vs spaces" debate does not exist in Go: gofmt uses tabs, and that is the end of the discussion.

Dart: dart format

Dart's official formatter, dart format, is the standard for Dart and Flutter projects. Like gofmt, it is opinionated and produces consistent output with minimal configuration. It is integrated into the Dart SDK and is typically run as part of CI pipelines for Dart projects. The dart format command enforces Dart's official style guide, which specifies 2-space indentation, trailing commas for multi-line collections, and specific patterns for line breaking in long expressions.

Rust: rustfmt

rustfmt is Rust's official formatter, installed alongside the Rust toolchain. It formats code according to the Rust style guide and is widely adopted across the Rust ecosystem. While it offers more configuration options than gofmt, the community convention is to use the defaults. Running cargo fmt before every commit is standard practice in Rust development.

Python: Black

Black describes itself as "the uncompromising Python code formatter." It follows the same philosophy as gofmt and Prettier: minimize configuration to eliminate debates. Black has very few options (line length and a handful of flags) and produces deterministic output. Its adoption in the Python community has grown rapidly because it frees teams from maintaining and debating Python style guides.

Key insight: The best formatting tool is the one your entire team actually uses. The specific style choices matter far less than having a single, automated tool that applies them consistently. Pick a formatter, accept its defaults, and move on.

Setting Up Auto-Format on Save

The most effective way to use a formatter is to configure your editor to run it automatically every time you save a file. This eliminates the need to remember to run the formatter manually and ensures that your code is always properly formatted.

In VS Code, add this to your workspace settings (.vscode/settings.json):

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "[python]": {
    "editor.defaultFormatter": "ms-python.black-formatter"
  },
  "[dart]": {
    "editor.defaultFormatter": "Dart-Code.dart-code"
  }
}

By committing this settings file to your repository, every developer who opens the project in VS Code gets auto-format-on-save configured automatically. This is a zero-friction way to ensure consistency without requiring each developer to configure their editor manually.

For JetBrains IDEs (IntelliJ, WebStorm, PyCharm), enable "Reformat Code" in the "Actions on Save" settings. For Prettier specifically, install the Prettier plugin and enable "Run on save."

Integrating with Pre-Commit Hooks

Auto-format-on-save handles the common case, but it does not catch every situation. A developer might use an editor without the formatter configured, edit a file through the GitHub web interface, or have their editor extension temporarily disabled. Pre-commit hooks provide a safety net.

A pre-commit hook runs automatically before every git commit. Combined with a tool like lint-staged, it runs the formatter only on staged files, keeping the hook fast. Here is a typical setup using Husky and lint-staged in a JavaScript project:

// package.json
{
  "lint-staged": {
    "*.{js,ts,jsx,tsx,css,json,md}": "prettier --write"
  }
}

With this configuration, every committed file is automatically formatted before the commit is created. If the formatter changes any files, the changes are included in the commit. The developer never sees unformatted code in the repository.

For polyglot projects, the pre-commit framework supports hooks for formatters across multiple languages:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
  - repo: https://github.com/psf/black
    rev: 24.1.0
    hooks:
      - id: black
  - repo: https://github.com/doublify/pre-commit-rust
    rev: v1.0
    hooks:
      - id: fmt

Why Automated Formatting Eliminates Style Debates

Style debates are a well-known source of friction in software teams. They arise because formatting preferences are deeply personal — developers have strong opinions about how code should look, and these opinions are often informed by years of habit. The problem is that these debates have no objectively correct answer. Tabs and spaces are both fine. Semicolons and no-semicolons are both fine. Opening braces on the same line and on the next line are both fine.

Automated formatting resolves this by making the decision once, mechanically, and enforcing it without human intervention. The key psychological insight is that people accept machine-imposed decisions more easily than human-imposed ones. When a human colleague says "you should use single quotes," it feels like a personal preference being imposed. When Prettier changes double quotes to single quotes, it feels like a project convention being applied — impersonal and consistent.

The result is that teams with automated formatting spend zero time discussing style in code reviews. Every pull request is already formatted correctly. The formatter is the final authority on style, and its decisions are not up for debate. This frees the team to spend their code review time on what actually matters: logic, architecture, security, and correctness.

A Complete Formatting Workflow

Putting it all together, here is the recommended formatting workflow for a quality-oriented team:

  1. Choose your tools. Pick Prettier (or a language-specific formatter) and EditorConfig. Accept the defaults or make a small number of deliberate choices.
  2. Commit configuration files. Add .prettierrc, .editorconfig, and .vscode/settings.json (or equivalent for your editor) to the repository.
  3. Set up auto-format-on-save. Configure every team member's editor to format on save.
  4. Add pre-commit hooks. Install Husky and lint-staged (or pre-commit) to catch unformatted code before it enters the repository.
  5. Add a CI check. Run the formatter in "check" mode (prettier --check) in your CI pipeline. This fails the build if any committed files are not properly formatted, catching any case where the editor and pre-commit hooks were bypassed.
  6. Format the existing codebase. Run the formatter once across the entire codebase and commit the result as a single formatting commit. This creates a clean baseline. Use git blame --ignore-rev to hide the formatting commit from blame output.

This layered approach provides multiple opportunities to catch unformatted code: at write time (editor), at commit time (pre-commit hook), and at merge time (CI pipeline). No unformatted code can reach the main branch.

Resources