⚠️ Design system CSS not found. Check the path in cms/docs.config.js → designSystemPath, then re-run npm run docgen.

JavaScript

JavaScript coding standards and organization guidelines

Docs / JavaScript
Download .md file
Open .md in new tab

Overview

This structure ensures readable, modular, and maintainable JavaScript with clear organization.


File Structure

Every JavaScript file should follow this organizational pattern:

/**
 * Script Purpose: [Brief description]
 * Author: [Your Name]
 */

console.log("Script Name loaded");

//
//------- Utility Functions -------//
//

function utilityFunction() {
  // ... implementation
}

//
//------- Main Functions -------//
//

function initComponent() {
  // ... implementation
}

//
//------- Event Listeners -------//
//

function setupEventListeners() {
  // ... implementation
}

//
//------- Initialize -------//
//

document.addEventListener("DOMContentLoaded", () => {
  initComponent();
  setupEventListeners();
});

Section Organization

  1. File header. Short comment block with purpose and author.
  2. Console log. One console.log() at the top to confirm the script loaded.
  3. Utility functions. Reusable helper functions grouped together.
  4. Main functions. Primary functionality grouped together.
  5. Event listeners. Event handling functions grouped together.
  6. Initialize. All setup calls within a single DOMContentLoaded listener at the end.

Section Dividers

Use a three-line divider to separate major groupings. The blank // lines above and below give it visual weight that sets it apart from ordinary comments:

//
//------- Section Name -------//
//

Most functions need no comment above them if the name is clear. Add one only when the purpose is not obvious from the name:

// Recalculates positions after the Barba page transition finishes
function refreshLayout() {
  // ... implementation
}

Variables

Use const by default. Use let only when you need to reassign the value. Never use var.

const maxItems = 10;     // never reassigned
let scrollPos = 0;       // updated as the user scrolls

var has confusing scoping behaviour and should not appear in any file.


Naming Conventions

Type Example Rule
Functions initSlider(), handleClick() Use lower camelCase, clear and descriptive
Variables mainElement, scrollPos Use lower camelCase, clear and descriptive
File Names slider.js, utils.js Use lowercase kebab-case
Constants MAX_ITEMS, API_URL Use UPPER_SNAKE_CASE

Name things for clarity, not brevity. Use as many words as needed to make the meaning obvious, then stop. A longer name that reads clearly beats a short one that does not: submitButton is better than btn, and event is better than e. Keep it short only when the shorter version is just as clear.


Initialization Pattern

  1. Define utility functions first.
  2. Define main functions grouped by section.
  3. Define event listeners separately.
  4. Call everything within a single DOMContentLoaded listener at the end.

Re-initialization on SPA Navigation

DOMContentLoaded fires once per full page load. On a site with client-side navigation (Barba or any SPA router), the fetched page's scripts never execute and DOMContentLoaded never re-fires — a module initialized only from DOMContentLoaded silently breaks after the first navigation.

On such a site, each module exposes its init and registers it twice: once for the initial load, once for the router's after-navigation event (the studio site fires studio:after-nav from its Barba hooks).

function initGallery() {
  const gallery = document.querySelector("[data-gallery]");
  if (!gallery || gallery.dataset.initialized) return;
  gallery.dataset.initialized = "true";
  // ... implementation
}

//
//------- Initialize -------//
//

document.addEventListener("DOMContentLoaded", initGallery);
document.addEventListener("studio:after-nav", initGallery);

Rules:

  • Init functions must be idempotent. Both events can hit the same DOM, so guard against double-init (the data-initialized pattern above).
  • Tear down what you set up. Listeners, observers, and animation timelines bound to the old page must be removed in the router's before-leave hook, or they leak across navigations.
  • The single-initialize-section rule still applies. The after-nav listener sits beside the DOMContentLoaded listener at the end of the file, not scattered through it.

Commenting

Comment the why, not the what. Well-named code already explains what it does, so a comment earns its place only when it explains something the code cannot: a decision, a workaround, or behaviour that is not obvious.

Skip comments that just restate the code:

// Get the button
const button = document.querySelector(".btn");

Keep comments that explain something non-obvious:

// 50ms delay needed because the Barba transition is still painting
setTimeout(initSlider, 50);

The goal is fewer, more useful comments. Too many comments make code harder to read, not easier, because the logic gets buried in prose.


Console Logging

Include one console.log() at the top of each script to confirm it has loaded. Do not scatter console logs throughout the code.


Early Returns

Exit a function early instead of wrapping its body in a large if. This keeps the main logic flat and easier to follow:

// Avoid
function init(element) {
  if (element) {
    // ... lots of code
  }
}

// Prefer
function init(element) {
  if (!element) return;
  // ... lots of code
}

Deeply nested conditionals are the most common thing that makes code hard to read. Handle the exit cases first, then write the main logic at the top level.


Magic Numbers

Avoid bare numbers whose meaning is not obvious. Give them a named constant so the value explains itself and can be changed in one place:

// Avoid
setTimeout(initSlider, 50);

// Prefer
const transitionDelay = 50;
setTimeout(initSlider, transitionDelay);

File Length

Keep each file focused on one component or concern. When a file grows past roughly 200 to 300 lines, or starts handling two unrelated things, split it into separate files. This keeps the single DOMContentLoaded pattern clean and makes each file easier to read.


Rules to Follow

Organization

  • Group related functions together
  • Use section dividers for major groupings
  • Place initialization at the end
  • Keep utility functions separate from main functions

Commenting

  • Include a short file header with purpose and author
  • Comment the why, not the what
  • Comment a function only when its name does not make the purpose clear
  • Use section dividers for major groupings

Code Quality

  • Use descriptive function and variable names, clear over short
  • Use lower camelCase for functions and variables
  • Use const by default, let when reassigning, never var
  • Use early returns to avoid deep nesting
  • Replace magic numbers with named constants
  • Follow naming conventions consistently
  • Place initialization in a DOMContentLoaded listener (plus the router's after-nav event on SPA sites)

What to Avoid

  • Scattering related functions across the file
  • Mixing utility functions with main functions
  • Multiple initialization points
  • Excessive console logging
  • Comments that restate what the code already says
  • Files that handle more than one concern
On this page
  • Overview
  • File Structure
  • Section Organization
  • Section Dividers
  • Variables
  • Naming Conventions
  • Initialization Pattern
  • Re-initialization on SPA Navigation
  • Commenting
  • Console Logging
  • Early Returns
  • Magic Numbers
  • File Length
  • Rules to Follow
Previous Tools

LLM Reference

Next

CSS

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default