ES6 incl. unit-testing & documentation
An example structure:
// queue.js - queue with concurrency limit
class Queue extends Array {
enqueue = (...values) => (this.push(...values), this);
dequeue = () => this.shift();
peek = () => this.at(0);
race = async (fn, { max = 3 } = {}) => {
const exec = async (inactive, inflight = [], finished = []) => {
if (!inactive.length && !inflight.length) return finished;
const dispatch = (elem) => fn(elem).then((result) => ({ result }));
const required = Math.min(max - inflight.length, inactive.length);
const starting = inactive.slice(0, required).map(dispatch);
const tracking = [...inflight, ...starting],
resolved = await Promise.race(tracking);
return exec(
inactive.slice(required),
tracking.filter((p) => p !== resolved),
[...finished, resolved.result],
);
};
return new Queue(...(await exec([...this])));
};
}- Layer functions by purpose
- Separate logic from side effects
- Skip needless intermediates
- Avoid nesting; use early returns
- Separate function steps with blank lines
- Name concisely and precisely
- Use short, contextual names
- Drop redundant qualifiers
- Use namespacing for structure
- Avoid needless semis, parens or braces
- Keep short controls inline
- Prefer arrows & implicit return
- Avoid pointless exotic syntax
- Consider iteration over repetition
- Keep lines ≤80; wrap by structure
- Use 70 characters for comments
- Prefer expressions over statements
- Stay immutable where possible
- Avoid (most) imperative loops
- Chain methods over nesting calls
- Use built-in test runner
- Structure tests hierarchically
- Write focused tests
- Attach fixtures to test context
- Use context for test utilities
- Assert the minimum required
- Test for keywords, not sentences
- Line breaks and spacing
- Write concisely and directly
- Use reference-style links
- Add whitespace between headers and content
Hard-wrap at 80. Width is a ceiling, not a target.
Wrap early for structure—even if the line is 79.
- No
elseblocks. Use guards, locals, or nested ternaries. - Operators at EOL. Break after
||,&&,+,-, etc. - Chains vertical. One call per line with a leading dot.
- Ternaries by structure. Split when nested; keep simple ones inline.
// ✅ guard without else
if (!ready) return;
start();
// ❌ fits under 80 but dense
const ok = () => foofoobarbar() || (barbarfoofoo() && bazbazbarbar(10) > 5);
// ✅ wrap by structure; make precedence explicit
const ok = () => foofoobarbar() || (barbarfoofoo() && bazbazbarbar(10) > 5);
// ❌ nested ternary crammed on one line
const level = (user) => (user.admin ? "admin" : user.mod ? "mod" : "user");
// ✅ split nested ternary
const level = (u) => (user.admin ? "admin" : user.mod ? "mod" : "user");
// ❌ long chain kept inline because "it fits"
foobarbaz().barbazfoo().bazfoobar().foobazbar() + extra();
// ✅ verticalize chains; operator at end
foobarbaz().barbazfoo().bazfoobar().foobazbar() + extra();ES modules are the JavaScript standard.
- Avoid
.mjs; prefer.jswith ESM flag. - Use
node:*imports for built-ins.
// ✅ ES modules
import { readFile } from 'node:fs/promises'
import { users, products } from './data.js'
import target from './target.js' with { type: 'json' }
import config from './config.js'
export const process = data => transform(data)
export const validate = input => check(input)
export default { process, validate }
// ❌ CommonJS
const fs = require('fs')
const { users } = require('./data')
module.exports = { process, validate }
// ✅ minimally publishable package.json
// NOTE: replace values as appropriate
{
"name": "@johndoe/foo",
"version": "1.0.0",
"description": "Does foo bar & maybe baz",
"type": "module",
"exports": "./index.js",
"files": ["index.js"],
"engines": { "node": ">=22" },
"scripts": { "test": "node --test" },
"keywords": ["foo", "bar"],
"author": "John Doe <[email protected]>",
"license": "MIT"
}Every dependency is a liability.
Prefer built-ins and writing small utilities.
// ✅ Use built-ins
const unique = [...new Set(items)];
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const pick = (obj, keys) =>
keys.reduce((acc, k) => ({ ...acc, [k]: obj[k] }), {});
// ❌ Don't install a package for one-liners
import uniq from "lodash.uniq"; // 4.4KB for [...new Set()]
import delay from "delay"; // 2.8KB for Promise + setTimeoutHowever, avoid DIY in production for domains that are:
- Too complex (game engines, CRDTs, date/time math)
- Too critical (cryptography, validation)
- Utility: Generic non-domain helpers
- Domain: Domain-specific helpers
- Orchestration: Usually the
mainof the module, program etc
// ✅ Utility functions
const gzip = (file) => compress(file, "gzip", { lvl: 1 });
const type = (file) => (ext) => file.filename.includes(ext);
// ✅ Domain functions
const upload = async (file, n = 0) => {
const result = await s3.upload(file);
return result.error ? (n <= 3 ? upload(file, ++n) : ignore(file)) : result;
};
// ✅ Orchestration functions
const synchronize = async (files) => {
const timedout = delay(30000);
const eligible = files.filter(type("png")).map(gzip);
const uploaded = await Promise.all(eligible.map(upload));
const response = await Promise.race([uploaded, timedout]);
return response === timedout ? ontimeout(eligible) : normalize(response);
};- Prefer pure functions over side effects
- Move side effects to boundaries
- Extract dependencies for easier mocking
// ✅ Testable - pure function
const discount = (price, pct) => price * (pct / 100);
// ✅ Testable - dependency injection
const notify = (user, emailer) => emailer.send(user.email, "Welcome!");
// ❌ Hard to test - side effects
const applyDiscount = (price, percentage) => {
const discount = price * (percentage / 100);
updateDatabase(discount);
sendEmail(discount);
return discount;
};
// ❌ Hard to test - hard-coded dependency
const notify = (user) => EmailService.send(user.email, "Welcome!");Extract dependencies when the function:
- Reaches outside your process space, e.g: network requests, filesystem
- Depends on uncontrollable factors (timers, accelerometers)
- Is slow or generally awkward to test
- Needs different implementations in different contexts
However, every indirection adds complexity.
Extract only when the benefit outweighs the cost.
// ✅ Simple operations don't need extraction
const formatName = (first, last) => `${first} ${last}`;
// ❌ Needless indirection
const formatName = (first, last, formatter) => formatter.format(first, last);Chain or inline unless the intermediate clarifies complex logic.
// ✅ No intermediates needed
const promote = (users) => users.map(review).filter(passed);
// ❌ Needless intermediates
const promote = (users) => {
const reviewed = users.map(review);
const eligible = reviewed.filter(passed);
return eligible;
};However, some functions naturally orchestrate others.
Don't mangle business logic for brevity—but don't make it
intentionally verbose either.
Early returns flatten code and eliminate edge cases upfront.
Each guard clause removes a level of indentation, making the
happy path obvious.
- Prefer guard returns; avoid
elseblocks where possible.
// ✅ Early return
onUpdate(fence) {
if (this.insulated)
return
if (!this.intersects(fence))
return this.electrocute()
// ... fancy sync logic
}
// ❌ Nested conditions
onUpdate(fence) {
if (!this.insulated) {
if (this.intersects(fence)) {
// ... fancy sync logic
} else {
this.electrocute()
}
}
}However, don't use them defensively.
Fix the caller instead of guarding against bad inputs.
Group guards, declarations, and logic into distinct visual blocks. One blank line between groups makes structure scannable.
// ✅ Good: clear visual grouping
const processUser = (user) => {
if (user.id === 10) return null;
const retries = 3;
const timeout = 5000;
for (const email of getUserEmails(user)) sendNotification(email);
if (isActive(user)) updateLastSeen(user);
return fetchProfile(user);
};// ❌ Bad: no visual separation
const processUser = (user) => {
if (user.id === 10) return null;
const retries = 3;
const timeout = 5000;
for (const email of getUserEmails(user)) sendNotification(email);
if (isActive(user)) updateLastSeen(user);
return fetchProfile(user);
};Pattern: guards → declarations → logic → return, each separated by blank line.
However, avoid blank lines to preserve intermediates; prefer chaining:
// ✅ Functional: no intermediates needed
const promote = (users) => users.map(review).filter(passed);
// ❌ Avoid forcing intermediates just for spacing
const promote = (users) => {
const reviewed = users.map(review);
const eligible = reviewed.filter(passed);
return eligible;
};Name by role, not by type.
Choose single words when precise alternatives exist, however...
"There are only two hard things in Computer Science:
cache invalidation and naming things."
— HRM Queen Elizabeth II
// ✅ Good
users;
active;
name;
overdue; // more precise than isPaid
// ❌ Avoid
userList;
isUserActive;
firstName;
lastName;
isPaid; // when overdue is clearerAssume the surroundings provide the context.
// ✅ Context eliminates redundancy
const user = { name, email, age }; // not userName, userEmail, userAge
const { data, status } = response; // not responseData, responseStatus// ❌ Redundant qualifiers
const user = { userName, userEmail, userAge };
const { responseData, responseStatus } = response;- Strongly prefer domain-relevant names; if none exists, don’t force jargon—pick the clearest generic name.
- Avoid single-letter params; use domain nouns; shorten with scope.
- Name by intent; drop type/structure noise.
- Exit condition: if a domain term would be obscure or disputed, use a clear generic name now; rename when a stable term emerges.
// ❌ negated passive
invoice.hasNotBeenPaid;
// ✅ domain term
invoice.overdue;// ❌ forced domain jargon in a generic util
const chunk = (ledgerEntries, size) => {
/* ... */
};
// ✅ clear generic when no domain term fits
const chunk = (items, size) => {
/* ... */
};// ❌ single-letter params, vague predicate
const canEdit = (u, r) => u.role === "admin" || u.id === r.ownerId;
// ✅ domain nouns, adjective predicate
const editable = (user, resource) =>
user.role === "admin" || user.id === resource.ownerId;// ❌ type/structure noise
const userArray = await repo.list();
// ✅ intent + context
const users = await repo.list();Group related properties under logical objects.
Avoid meaningless wrappers or technical groupings.
// ✅ Appropriate namespacing
const user = {
name: { first, last, full },
contact: { email, phone },
status: { active, verified },
};
const config = {
server: { port, host },
database: { url, timeout },
};
// ❌ Inappropriate namespacing
const user = {
data: { value: "John" }, // Meaningless wrapper
info: { type: "admin" }, // Generic grouping
props: { id: 123 }, // Technical grouping
};Minimal syntax, maximum signal.
// ✅ Minimal syntax
const name = "Alice";
const double = (x) => x * 2;
const greet = (name) => `Hello ${name}`;
users.map((user) => user.name);
if (subscribers.length) throw new Error("Session is subscribed");
const user = { name, email, age };
// ❌ Unnecessary syntax
const name = "Alice";
const double = (x) => {
return x * 2;
};
users.map((user) => user.name);
const user = { name: name, email: email };Brief control structures stay readable on one line; longer ones break to preserve scannability and enable line-by-line review.
// ✅ Good: under ~40 chars, keep inline
if (authenticated) redirect("/dashboard");
if (!user) return;
// Ternaries when simple
const price = member ? applyDiscount(base) : base;
// Over ~40 chars: break to next line
if (authenticated && verified && !suspended) redirect("/dashboard");
for (const item of cart.items) calculateTotal(item.price, item.quantity, tax);// ❌ Bad: long conditions crammed on one line
if (authenticated && verified && !suspended) redirect("/dashboard");
for (const item of cart.items) calculateTotal(item.price, item.quantity, tax);
// Simple enough for one line but unnecessarily broken
if (ready) start();However:
- Never inline
elseblocks (use early returns instead) - Break nested structures regardless of length (flatten with guards)
- Break
try/catch/finallyfor clarity - Break when total line exceeds 80 characters
Skip braces and return for single expressions.
// ✅ Implicit return
const double = (x) => x * 2;
const getName = (user) => user.name;
const sum = (a, b) => a + b;
const makeUser = (name, age) => ({ name, age });
// ❌ Explicit return for single expressions
const double = (x) => {
return x * 2;
};
const getName = (user) => {
return user.name;
};
const makeUser = (name, age) => {
return { name, age };
};Choose clarity over cleverness.
Use language features when they improve readability, not just because.
// ✅ Clear intent
const isEven = (n) => n % 2 === 0;
// ❌ Clever but unclear
const isEven = (n) => !(n & 1);Two items? Maybe copy-paste.
Three or more? Use a loop for easier extension.
// ✅ Dynamic generation
return ["get", "put", "post", "patch"].reduce(
(acc, method) => ({ ...acc, [method]: send }),
{},
);
// ❌ Manual enumeration
return { get: send, put: send, post: send, patch: send };Avoid overuse, especially in tests; loops need mental parsing.
// ❌ Overabstracted test
["admin", "user", "guest"].forEach((role) => {
test(`${role} access`, (t) => {
const result = checkAccess(role);
t.assert.strictEqual(result, role === "admin");
});
});
// ✅ Clear, explicit tests
test("admin has access", (t) => {
t.assert.strictEqual(checkAccess("admin"), true);
});
test("user lacks access", (t) => {
t.assert.strictEqual(checkAccess("user"), false);
});
test("guest lacks access", (t) => {
t.assert.strictEqual(checkAccess("guest"), false);
});- Strongly prefer wrapping <60.
- Break by structure even under 80; add hard line breaks at natural boundaries (operators, delimiters, chain links); keep grouping obvious; don’t collapse.
// ❌ dense, mixed precedence
const ok = () => a() || (b() && c(10) > 5);
// ✅ wrap by structure; keep group parens; hard breaks at boundaries
const ok = () => a() || (b() && c(10) > 5);// ❌ long chain kept inline because "it fits"
api().get().map().filter().reduce() + extra();
// ✅ one call per line; operator at end; hard breaks per link
api().get().map().filter().reduce() + extra();Comments are a maintenance burden.
Reserve them for explaining "why", not "what".
// ✅ Explaining unusual approach
// Polling needed due to API limitations
while (!response.complete) await request(query, { delay: 200 });
// ❌ Obvious comments
const total = prices.reduce((sum, price) => sum + price, 0); // sum pricesWhen converting data, think pipelines not procedures.
// ✅ Functional for transformations
const users = data.filter(active).map(normalize).sort(by.name);If it has identity and changes over time (User, Game, Session), make it a class.
// ✅ OOP for entities
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
evaluate = () => this.score > 80;
promote = () => {
this.role = "senior";
return this;
};
}Expressions return values and compose.
// ✅ Good: ternaries over if
const upload = async (file, n = 0) => {
const result = await s3.upload(file);
return result.err ? (n <= 3 ? upload(file, ++n) : ignore(file)) : result;
};
// ✅ Good: object lookup over switch/case
const handle = (action) =>
({
create: () => save(data),
update: () => modify(data),
delete: () => remove(data),
})[action]?.() || cancel();// ❌ Avoid
switch (action) {
case "create":
return save(data);
case "update":
return modify(data);
case "delete":
return remove(data);
default:
return defaultAction();
}Use a concise arrow only when the body is a single clear expression (≈≤60); otherwise keep the grouped steps.
// from above: paginate
const paginate = (xs, page = 1, size = 25) =>
!Array.isArray(xs) || page < 1 || size < 1
? []
: xs.slice((page - 1) * size, page * size);[...arr, item] not arr.push(item).
New values are easier to debug than mutations.
// ✅ Immutable
const add = (users, user) => [...users, user];
const update = (user, data) => ({ ...user, ...data });
// ❌ Mutating
const add = (users, user) => users.push(user);
const update = (user, data) => Object.assign(user, data);prices.filter(discounted) tells what's happening.
A for loop makes you figure it out.
// ✅ Functional approach
const active = users.filter((user) => user.active);
const names = users.map((user) => user.name);
const total = prices.reduce((sum, price) => sum + price, 0);
// ✅ Sequential async operations
for (const file of files) await fetch(file);
// ❌ Imperative loops
const active = [];
for (let i = 0; i < users.length; i++) {
if (users[i].active) {
active.push(users[i]);
}
}Inside-out is hard. Top-to-bottom is natural.
// ✅ Multi-line chaining
const process = (data) =>
data
.filter((x) => x > 0)
.map((x) => x * 2)
.reduce((a, b) => a + b);
// ❌ Nested function calls
const process = (data) =>
reduce(
map(
filter(data, (x) => x > 0),
(x) => x * 2,
),
(a, b) => a + b,
);animation.fadeIn().wait(300).slideOut()
Each method returns the object for the next.
// ✅ Method chaining
class Calculator {
constructor(val = 0) {
this.val = val;
}
add = (n) => new Calculator(this.val + n);
mul = (n) => new Calculator(this.val * n);
get = () => this.val;
}
// Usage: new Calculator(5).add(3).mul(2).get() // 16
// ✅ Builder pattern for async workflows
const query = select("name", "email")
.from("users")
.where("active", true)
.where("role", "admin")
.orderBy("name")
.limit(10);
// ✅ Domain-specific naming
const animation = animate(element)
.to({ opacity: 0, x: 100 })
.duration(300)
.easing("ease-out")
.then(() => element.remove());Trust your code; no trust, write tests.
Definitely don't litter the place with guard clauses.
// ✅ Trust internal functions
const process = (data) => data.filter(active).map(normalize);
// ❌ Defensive programming within internal functions
const process = (data) => {
if (!data || !Array.isArray(data)) return [];
return data
.filter((item) => item && active(item))
.map((item) => (item ? normalize(item) : null))
.filter(Boolean);
};
// ❌ Defensive early returns
const formatName = (first, last) => {
if (!first) return ""; // Why is caller passing empty names?
if (!last) return ""; // Fix the caller instead
return `${first} ${last}`;
};
// ✅ Trust the caller
const formatName = (first, last) => `${first} ${last}`;Exception: External data must be validated.
Be specific:
- Wrong type?
TypeError - Out of bounds?
RangeError - Everything else?
Errorwith a clear message
// ✅ Specific error types
if (typeof value !== "number")
throw new TypeError(`Expected number, got ${typeof value}`);
if (value < 0 || value > 100)
throw new RangeError("Value must be between 0 and 100");
if (!process.env.API_KEY) throw new Error("API_KEY missing");
// ❌ String errors
throw "Invalid value";
// ❌ Generic errors
throw new Error("Invalid input");Users add spaces.
Environment variables arrive as strings.
Clean everything at the borders.
// ✅ Environment variables
const port = parseInt(process.env.PORT || "3000", 10);
const env = (process.env.NODE_ENV || "development").toLowerCase();
// ✅ Booleans
const enabled = /^(true|1|yes|on)$/i.test(process.env.ENABLED || "");
// ✅ Arrays from CSV
const hosts = (process.env.HOSTS || "")
.split(",")
.map((s) => s.trim())
.filter(Boolean);
// ✅ User input
const email = (input || "").trim().toLowerCase();
// ❌ No normalization
const port = process.env.PORT; // Could be undefined/string
const enabled = process.env.ENABLED; // String, not booleanValidation:
// ✅ Validate at boundaries
const handleRequest = (req) => {
if (!req.body?.userId) throw new Error("userId required");
if (typeof req.body.userId !== "string")
throw new TypeError("userId must be string");
return processUser(req.body.userId);
};
// ✅ Early validation
const createUser = (data) => {
if (!data.name) throw new Error("Name required");
if (!data.email) throw new Error("Email required");
// Trust internal processing
return save(normalize(data));
};
// ❌ Late validation
const processUser = (data) => {
const result = expensiveOperation(data);
if (!data.name) throw new Error("Invalid data"); // Too late
return result;
};Since Node v19: node --test.
Zero dependencies.
Node v24+ automatically awaits subtests, eliminating a major source of flaky tests.
// ✅ Built-in test runner
// Run with: node --test
import { test } from "node:test";
// ❌ External dependencies
import { describe, it } from "jest";
import { expect } from "chai";Tests tell a story: component → scenario → expectation.
Nest them that way.
Write for non-technical readers—including future you.
You won't remember the context when it breaks.
// ✅ Hierarchical structure
test("#withdraw", (t) => {
t.test("amount within balance", (t) => {
t.test("disperses requested amount", async (t) => {
// assertion with await
});
});
t.test("amount exceeds balance", (t) => {
t.test("throws appropriate error", async (t) => {
// assertion with await
});
});
});
// ❌ Flat structure
test("withdraw disperses amount when within balance", (t) => {});
test("withdraw throws when amount exceeds balance", (t) => {});One test, one assertion, one failure reason.
// ✅ Granular tests
test("#withdraw", (t) => {
t.test("within balance", (t) => {
t.test("returns updated balance", async (t) => {
t.assert.strictEqual(await t.atm.withdraw(30), 70);
});
});
});
// ❌ Multiple assertions, redundant titles
test("ATM withdrawal when amount is within available balance should disperse the requested amount and update balance", async (t) => {
const initial = t.atm.balance;
const result = await t.atm.withdraw(30);
t.assert.strictEqual(result, 70);
t.assert.strictEqual(t.atm.balance, 70);
t.assert.strictEqual(initial - 30, t.atm.balance);
t.assert.ok(t.atm.lastTransaction);
});Attach test data directly to the context using
t.beforeEach(t => t.atm = new ATM(100)).
Avoid external variables or imports for fixtures.
// ✅ Context fixtures
test("#withdraw", (t) => {
t.beforeEach((t) => (t.atm = new ATM(100)));
t.test("disperses amount", async (t) => {
await t.atm.withdraw(30); // t.atm available
});
});
// ❌ External fixtures
let atm; // External variable
beforeEach(() => {
atm = new ATM(100);
});
test("disperses amount", async (t) => {
await atm.withdraw(30);
});Everything's on t: t.assert, t.mock, t.beforeEach.
t.mock resets automatically between tests.
// ✅ Context utilities
test("#notify", (t) => {
t.test("sends email", (t) => {
const emailer = t.mock.fn();
notify(user, { send: emailer });
t.assert.strictEqual(emailer.mock.calls.length, 1);
});
});
// ❌ Imported utilities
import { assert, mock } from "node:test";
test("sends email", (t) => {
const emailer = mock.fn();
// ...
assert.strictEqual(emailer.mock.calls.length, 1);
});Don't test what you don't care about,
especially if the object is expected to be extended.
// ✅ Partial assertions
test("#user properties", (t) => {
t.test("has correct details", (t) => {
t.assert.partialDeepStrictEqual(t.user, {
name: "Alice",
role: "admin",
});
});
});
// ❌ Full object matching
test("has correct details", (t) => {
t.assert.deepStrictEqual(t.user, {
id: "123",
name: "Alice",
role: "admin",
createdAt: new Date("2024-01-01"),
updatedAt: new Date("2024-01-01"),
// ... all properties
});
});Match keywords that survive rephrasing:
"Insufficient balance" → "You have insufficient funds"
However, pick keywords unique to the test:
- ✓
/insufficient/- specific to this error - ✗
/balance/or/invalid/- too generic
Otherwise your test becomes junk.
// ✅ Flexible matching
test("#withdraw", (t) => {
t.test("exceeds balance", async (t) => {
await t.assert.rejects(() => t.atm.withdraw(150), {
name: "Error",
message: /insufficient/i,
});
});
});
// ❌ Exact string matching
await t.assert.rejects(() => t.atm.withdraw(150), {
name: "Error",
message: "Insufficient funds: cannot withdraw 150 from balance of 100",
});Complete test example:
test("#atm", (t) => {
t.beforeEach((t) => (t.atm = new ATM(100)));
t.test("#withdraw", (t) => {
t.test("within balance", (t) => {
t.test("returns updated balance", async (t) => {
t.assert.strictEqual(await t.atm.withdraw(30), 70);
});
});
t.test("exceeds balance", (t) => {
t.test("throws error", async (t) => {
await t.assert.rejects(() => t.atm.withdraw(150), {
name: "Error",
message: /insufficient/i,
});
});
t.test("preserves balance", async (t) => {
await t.assert.rejects(() => t.atm.withdraw(150));
t.assert.strictEqual(t.atm.balance, 100);
});
});
});
t.test("#properties", (t) => {
t.test("has location and currency", (t) => {
t.assert.partialDeepStrictEqual(t.atm, {
location: "Main Street",
currency: "USD",
});
});
});
});- Headers: 3-5 words max
- 70-85 chars per line, break at 50+ to newline
- AVOID WRAPPING - start new line instead of wrapping long text
- One empty line before and after all headers and bold: labels
- 2-space hard line breaks where applicable
// ✅ Proper breaks and spacing
Configure the database.
Set DB_URL in your environment.
**Required:**
- Node 18+
- PostgreSQL
```js
const db = connect(url);
```Next section starts here.
// ❌ Poor formatting Configure the database connection by setting the DB_URL environment variable in your shell or configuration file. Required:
- Node 18+
const db = connect(url);Next section starts here.
### Write concisely and directly
Active voice. Matter-of-fact tone.
Under 20 words. Lists over paragraphs.
No emojis. Reference-style links.
```markdown
// ✅ Direct, scannable, technical
The server validates requests.
Requirements:
- Node 18+
- 2GB RAM
Processes 1000 requests/second.
See [node-docs] for details.
[node-docs]: https://nodejs.org/api
// ❌ Passive, verbose, marketing
Requests are validated by the server infrastructure 🚀
In order to run this powerful enterprise solution, you'll
need Node.js version 18 or higher and at least 2GB of RAM.
Lightning-fast performance at enterprise scale.
Link to authoritative sources.
Use a short, consistent, non-numeric format:
// ✅ Descriptive, consistent references
See the [node-docs] for details.
Based on [rfc-7231].
[node-docs]: https://nodejs.org/api/documentation.html
[node-util]: https://nodejs.org/api/util.html
[rfc-7231]: https://tools.ietf.org/html/rfc7231
// ❌ Numeric or inline URLs
See the [docs][1] for details.
See the [docs](https://nodejs.org/api/documentation.html).
[1]: https://nodejs.org/api/documentation.html// ✅ Linebreak before and after header
...rem Ipsum Dolor sit amet,
Lorem Ipsum Dolor, lorem Ipsum Dolor sit amet..
### Overview
Lorem Ipsum Dolor sit amet. Lorem Ipsum Dolor,
lorem Ipsum Dolor sit amet...
**lorem:**
Lorem Ipsum Dolor sit amet. Lorem Ipsum Dolor,
lorem Ipsum Dolor sit amet...
// ❌ content immediately follows a header/label.
...rem Ipsum Dolor sit amet,
Lorem Ipsum Dolor, lorem Ipsum Dolor sit amet..
### Overview.
Lorem Ipsum Dolor sit amet. Lorem Ipsum Dolor,
lorem Ipsum Dolor sit amet...
**lorem:**.
Lorem Ipsum Dolor sit amet. Lorem Ipsum Dolor,
lorem Ipsum Dolor sit amet...author: nicholaswmin, MIT