Best practices and coding guidelines
A guide for building better applications.
Don't follow this guide blindly. Read the references to learn more about certain rules. Some practices become outdated as the web evolves.
This page is a continuous work in progress.
Table of contents:
- Be an early evaluator, but late adopter.
- Provide 404 and 50x error pages.
- Inline all external resources on error pages (e.g. CSS, images).
- Test your website with adblockers enabled.
- Monitor your website's availability, e.g. with Uptime Robot.
- Offer an RSS feed for any kind of articles. Include the full content instead of snippets.
- Do not use protocol-relative URLs, e.g.
target="_blank"to improve performance and prevent security vulnerabilities.
asyncwhen loading scripts.
- Provide basic document metadata and boilerplate:
<meta name="viewport" content="width=device-width, initial-scale=1">
- Define favicons:
<link rel="icon" sizes="192x192" href="/favicon-192.png">
- Place paragraphs in a
<p>tag. Do not use multiple
- Do not write closing tag comments, e.g.
<!-- end .content -->.
- Do not set values for boolean attributes, such as
type, inputmode, autocomplete and enterkeyhint values to input fields if applicable. Test possible values here.
translate="no"for content that should not be translated.
- Avoid number inputs. If necessary, use number inputs only for real numeric values.
- Consider including normalize.css or sanitize.css before own stylesheets.
- Don't use @import.
- Avoid shorthand properties.
border-boxbox-sizing by default.
- Place media queries close to their relevant rule sets. Do not bundle them in a separate stylesheet or at the end of the document.
- Provide a print layout.
- Emulate print media in Chrome.
- Support forced-colors with custom properties.
- Remove unused CSS.
- Consider a utility-first approach.
- Use CSS containment when appropriate.
- Use relative units.
- When using
scroll-behavior: smooth, provide a workaround for the browser search.
- Ignore the performance impact of CSS selectors.
- Organize your files around features, not roles.
- Use subresource integrity for all external scripts.
- Use standardized keyboard event handling:
- Do not use the
- Don't attach tooltips to
- Consider using PureComponent over Component.
- Don't overuse useCallback.
- Pay attention to using
bindor arrow functions in
render()to avoid creating new values each render cycle.
- For functional components, use useCallback to memoize the callback.
- For class components, define the callback outside the
- As of React 16, functional components are slightly more performant than class components.
- Use code splitting to lazy load components that are not instantly needed with React.lazy and
- Use React.StrictMode.
- Be aware that StrictMode components may render twice in development mode.
- Never mutate props.
- Don't use array indexes as keys.
- Render lists in dedicated components.
- Rethink your mental model regarding
- Use multiple
useEffectcalls for independent concerns.
- Use ternaries rather than
- Prefer composition when creating reusable component abstractions.
- Use primitives in hook dependency arrays (
user.nameis being used).
- Do not mutate state.
- Do not put non-serializable values in state or actions.
- Prefer normalized state.
- Don't use isLoading booleans.
- Consider using inline SVGs instead of icon fonts.
- Use WEBP/AVIF images with a fallback for older browsers.
- Use responsive images, especially for Retina displays.
- Enforce a zero-warnings policy.
- Avoid handling code issues as warnings. Set linter rules to either "off" or "error".
- Invest time to come up with good names for variables, functions, etc.
- Include units in variable names.
- Avoid hasty abstractions.
- Prefer duplication over the wrong abstraction.
- Avoid adding lava layers, i.e., introducing new patterns on top of existing ones that solve the same problem.
- Use consistent coding conventions, automatically enforced.
- Think globally, act locally: create reusable components, but don't cover all theoretical future enhancements.
- Make impossible states impossible.
- Don't rely on code coverage alone.
- Use snapshot tests only when appropriate. Using snapshot tests for UI components is usually a bad idea.
- Find performance issues with Google's PageSpeed Insights.
- Enable gzip compression and test it.
- Choose readable code over micro performance optimizations such as performant CSS selectors or using a for loop over forEach.
- Serve videos instead of GIFs.
- Use priority hints (fetchpriority) to lower/increase the fetch priority of resources.
- Test your website with custom fonts disabled.
- Consider avoiding web fonts.
- Use Google WebFonts helper to create an optimized font subset.
- Preload your most important font files. You probably don't need to preload italic/bold variants.
- Consider trade-offs of performance best practices.
- Don't use system-ui font family.
- Ensure a thumb-friendly navigational design.
- Remove unnecessary borders from design elements.
- Consider replacing borders with box shadows.
- Avoid floating labels
- Avoid messages under fields.
- Use at least a 16px font size for inputs. This will also prevent zooming issues with iOS Safari.
- Use semantic HTML.
- Provide an alt text for all images. Use
alt=""for decorative images.
- Provide a
labelfor all form inputs. The
placeholderattribute is not a usable alternative.
- Write descriptive links.
- The contrast ratio between the background and the foreground should be as high as possible.
- Avoid low-contrast font colors.
- When using colors to communicate information (such as states or graphs), use different styles or add a text/icon to distinguish different states. This is important for both colorblind people and for printing a page in grayscale.
- The tab order should go from top to bottom, from left to right
- Do not use a
tabindexvalue greater than 0.
- Do not hide the focus ring without providing an alternative.
- Do not use a
- Be aware of screen reader conflicts with accesskeys, making accesskeys mostly useless for blind users.
- Make sure zooming in/out doesn't break the page.
- Avoid using icons without labels
- Ensure that interactive controls have at least a 44×44px target click size.
View my accessibility notes for more information.
- Use HTTPS everywhere. Yes, your site does need HTTPS.
- Test your SSL rating on SSL Labs.
- Define a Certificate Authority Authorization (CAA).
- Define a Referrer Policy.
- Define a Content Security Policy.
- Scan your website for security issues:
- Hash user passwords using a cryptographically strong algorithm, like Argon2, PBKDF2, Scrypt, or Bcrypt.
- Enable Two-Factor Authentication (2FA).
- Don't take
npm auditfindings at face value.
- Include a privacy notice.
- Comply with the EU Cookie Law.
- Check the cookies for a domain with Cookie Metrix.
- Collect only the bare minimum amount of data needed for its purpose.
- Do not opt in into Google's FLoC network.
- Verify your site in Google Search Console.
- Use canonical URLs to prevent search engines from indexing duplicate content.
- Provide a sitemap.
- Provide a robots.txt file.
- Keep title 60 characters or fewer.
- Keep meta descriptions 160 characters or fewer.
- Be consistent. Use familiar conventions and apply them consistently.
- Provide a way to try the app without signing up:
- Public demo.
- Guest account, which can be easily turned into a full account.
- Show a different view when there is no data, e.g. a tutorial link or description (examples).
- Only provide choices when a good default does not exist.
- Options can be costlier than features.
- Provide smart defaults based on frequently chosen input.
- Include something funny/goofy.
- Hide easter-eggs.
- Send custom HTTP headers.
- Provide a search feature, e.g. using OpenSearch.
- Ensure good visual stability: elements on the page should not shift in ways that users don't expect.
- Know when (not) to split a form field into multiple inputs.
- Don't use flags to represent a language
- Don't set the language of your website based on user location.
- Test for unnecessary scrollbars.
- Tie the sign-up button text to your product.
- Use the ellipsis character in menus to indicate an additional user input.
- When adding links to downloadable files, include information about the file's size and its format.
- Mark required input fields.
- Redirect a request to
/.well-known/change-passwordto the change-passwords URL.
- Provide screenshots in your web app manifest.
- Don't sort by average rating.
- Commit early and often. Perfect later.
- Copy/move a file in a different commit from any changes to it to retain the correct file history.
- Do not force-push public branches that other people are working on.
- Create a tag for each release using semantic versioning, e.g.
- Provide a social media image.
- Include guidelines for contributors in CONTRIBUTING.MD.
- Include a humans.txt file to acknowledge project contributors.
- Use npm scripts so no further build tools have to be installed or used.
- Consider recording a screencast or a console demo to demonstrate the setup and usage.
- Summarize your core idea in a single sentence (elevator pitch).
- Consider the purchasing power parity on product/service pricing.
- Prefer active voice to passive voice.
- Avoid ambiguous pronouns:
- In general, if more than five words separate your noun from your pronoun, consider repeating the noun instead of using the pronoun.
- If you introduce a second noun between your noun and your pronoun, reuse your noun instead of using a pronoun.
- it, they, them, their, this, that
- Pick specific verbs over vague ones. Reduce the usage of:
- be / is / are / am / was / were
- occur / happen
- there is / there are
- Keep list items parallel.
- Put conditional clauses before instructions, not after.
- Avoid unnecessary words:
- really, pretty much, quite a few, obviously, basically, simply, of course, clearly, just, everyone knows, very, a bit, a little, quite, too, though, sort of, kind of, rather
thatfor defining (= non-optional) clauses (no comma)
whichfor non-defining (= optional) clauses (comma)
- help (to) do:
-ingon the infinitive
- Historically, typographical curly apostrophes (
’) are preferred. On the web, typewriter straight apostrophes (
') are acceptable, too.
- Use correct dashes:
- Hyphen (
-): Compound words (e.g. "sign-in", "cost-effective").
- En dash (
–): Ranges (e.g. "1985–2022", "Mon–Tue").
- Em dash (
—): Break between parts of a sentence. Stronger than a comma, weaker than a semicolon.
- Hyphen (
- Effective teams need trust. Replacing trust with process is called bureaucracy.
- Start sprints on Wednesday to reduce the absence in sprint meetings due to days off and remote working.
- Use appropriate defect severities. Do not misuse them to express a (customer) prioritization.
- Severity 1 (Critical): System failure. No further processing is possible.
- Severity 2 (High): Unable to proceed with selected function or dependants.
- Severity 3 (Medium): Restricted function capability, however, processing can continue.
- Severity 4 (Low): Minor cosmetic deviance.
- Go remote-first. Build your development team around a workflow that embraces the concepts of remote work, whether or not your employees are remote.
- Prefer asynchronous communication.
- Always use a camera in addition to audio during remote meetings.
- No well-actually: Do not correct someone about something that's not relevant to the conversation or tangential to what they're trying to say.
- No feigning surprise: Do not act surprised when someone doesn't know something.
- No backseat driving: Do not lob advice from across the room (or across the online chat) without joining or engaging in a conversation.
- Avoid oppressive language
- Don't just say "hello" in a chat. Don't ask to ask.
- Plan for the worst-case scenario, e.g. your computer dying.
- Use a bright color theme on a beamer to improve readability (slides, console, editor/IDE).
- Be prepared to zoom in your presentation
- Prepare good verbal transitions between slides.
- Keep the things you say and the things you show in sync.