A developer on my team once introduced a bug that took four hours to find. The code looked like this:
if (user.isAdmin)
deleteAllRecords();
sendNotification("Records purged");
The indentation made it look like both lines were inside the if block. They were not. sendNotification ran unconditionally because JavaScript does not use indentation for scoping. Only the first statement after a braceless if is conditional. Every user -- admin or not -- received a "Records purged" notification.
Consistent formatting would have prevented this. Either braces would have made the scope explicit, or a formatter would have corrected the indentation to reflect the actual behavior:
if (user.isAdmin)
deleteAllRecords();
sendNotification("Records purged"); // clearly unconditional
This is why code formatting matters. Not because pretty code is easier to look at (though it is), but because misleading formatting causes real bugs that waste real time.
What beautifiers actually do
A code beautifier (or formatter) parses source code into an abstract syntax tree (AST), then regenerates the source text according to a set of style rules. The output is semantically identical to the input -- the program behaves exactly the same -- but the whitespace, line breaks, and bracket placement follow a consistent pattern.
The key transformations:
Indentation normalization. Mixed tabs and spaces are resolved to one style. Nested blocks are indented consistently. This is the most impactful change because indentation is how humans perceive code structure.
// Before: inconsistent indentation
function process(data) {
if (data.valid) {
return transform(data);
} else {
throw new Error("Invalid");
}
}
// After: consistent 2-space indentation
function process(data) {
if (data.valid) {
return transform(data);
} else {
throw new Error("Invalid");
}
}
Line length management. Long lines are wrapped at a configured maximum (80, 100, or 120 characters are common). The formatter decides where to break and how to indent the continuation. This is particularly impactful for function calls with many arguments and chained method calls.
Bracket placement. The "same line vs. next line" debate for opening braces. Formatters pick one style and apply it everywhere. K&R style (opening brace on the same line) is dominant in JavaScript. Allman style (opening brace on the next line) is common in C#. What matters is consistency, not which style you choose.
Semicolons and trailing commas. In JavaScript, formatters can add or remove optional semicolons and enforce trailing commas in multi-line arrays and objects. Trailing commas produce cleaner git diffs because adding a new item only changes one line instead of two.
Quote normalization. Single vs. double quotes. Template literals vs. string concatenation. These are pure style choices, but inconsistency within a file is distracting.
The case for automated formatting
The strongest argument for automated formatting is that it eliminates an entire category of code review discussions. I have watched teams spend 30 minutes in a pull request debating whether a ternary should be on one line or three. Multiply that by every PR and you are burning hundreds of engineering hours per year on decisions that have zero impact on correctness.
Automated formatters like Prettier, Black (Python), gofmt (Go), and rustfmt (Rust) take the decision away from humans. The code is formatted on save or as a pre-commit hook. Nobody argues about style because nobody has a choice.
// .prettierrc -- a minimal Prettier configuration
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
Go took this further: gofmt is built into the language toolchain and there are zero configuration options. Every Go file in every Go project in the world looks the same. Python's Black takes a similar "opinionated" approach with minimal configuration. The less you can argue about, the less you will argue about.
When beautification goes wrong
Formatting generated code. If your project includes auto-generated files (protocol buffers, GraphQL types, ORM migrations), do not run a beautifier over them. The generator's output format may be intentional, and reformatting can cause problems on regeneration. Add these paths to your formatter's ignore list.
Breaking meaningful alignment. Some code uses intentional column alignment for readability:
const STATUS_OK = 200;
const STATUS_CREATED = 201;
const STATUS_MOVED = 301;
const STATUS_ERROR = 500;
A formatter will collapse those spaces because it does not understand the intent. Prettier has an // prettier-ignore comment for these cases. Use it sparingly.
Inconsistent formatter versions. If one developer runs Prettier 2.x and another runs Prettier 3.x, they will produce different output for the same input. Pin your formatter version in package.json and use the project's version, not a global install.
Formatting without understanding. A beautifier can make poorly structured code look clean. Properly indented spaghetti is still spaghetti. Formatting is necessary but not sufficient for readability. It handles the surface-level presentation so you can focus your review energy on logic, architecture, and naming.
Tips for adopting a formatter on an existing project
Do a single "format the world" commit. Apply the formatter to the entire codebase in one commit with a message like "Apply Prettier formatting." This creates one noisy commit in git blame, but every subsequent commit is clean. Use git blame --ignore-rev or a .git-blame-ignore-revs file to skip the formatting commit in blame output.
Set up the pre-commit hook immediately. If the formatter is not enforced, developers will forget to run it, and you are back to inconsistent formatting within days. Use tools like husky (Node.js) or pre-commit (Python) to run the formatter on staged files before every commit.
Do not configure too much. The more options you configure, the more opinions your team needs to agree on. Adopt the formatter's defaults. If you must customize, change as few settings as possible.
For quick one-off formatting -- pasting in a snippet from a Stack Overflow answer, cleaning up code from a PDF, or reformatting a file from a project that uses a different style -- I keep a code beautifier at zovo.one/free-tools/code-beautifier that handles JavaScript, HTML, CSS, JSON, and other common languages.
Format your code automatically. Do not trust humans to be consistent, because we are not. Let the machine handle the pixels so you can focus on the logic.
I'm Michael Lip. I build free developer tools at zovo.one. 350+ tools, all private, all free.
Top comments (0)