Skip to content

WWW JavaScript Architecture

This document describes the organization and architecture of the WWW JavaScript codebase.

client/js/www/
├── www.index.js # Main entry point - orchestrates imports
├── application.js # Legacy app init (minimal, being phased out)
├── contactFormInit.js # Contact form dropdown handling
├── smart_services.js # Smart services checkout flow
├── setup/ # Core initialization modules
│ ├── turbo.js # Turbo Drive configuration
│ ├── stimulus.js # Stimulus controller registration
│ ├── bootstrap.js # Bootstrap component initialization
│ ├── csrf.js # CSRF token handling
│ ├── intl_tel_input.js # International phone input
│ ├── features.js # Declarative feature loader
│ └── app_init.js # Core app setup, phone tracking
├── include/ # External integrations
│ ├── externalScripts.js # CallRail loading
│ └── crispChatWrapper.js # Crisp chat integration
├── home/ # Home page specific
│ └── wwwHome.js # Home page initialization
├── euc/ # DEPRECATED - Energy Usage Calculator (React)
│ └── (migrated to ViewComponent: Www::FloorHeatingCalculatorComponent)
├── smeuc/ # DEPRECATED - Snow Melting EUC (React)
│ └── (migrated to ViewComponent: Www::SnowMeltingCalculatorComponent)
├── quotes/ # Quote Builder (React)
│ └── quoteBuilder.index.js # Entry point
└── rp/ # Room Planner (React)
└── rpEdit.index.js # Entry point

The main entry point orchestrates all JavaScript initialization:

// Setup modules (order matters)
import { initTurbo } from './setup/turbo';
import { initStimulus } from './setup/stimulus';
import { initBootstrap } from './setup/bootstrap';
import { initCsrf } from './setup/csrf';
import { initializeIntlTelInput } from './setup/intl_tel_input';
import { loadDeclaredFeatures } from './setup/features';
import { initApp, initWww } from './setup/app_init';

Configures Turbo Drive for SPA-like navigation:

  • Enables Turbo Drive
  • Sets up cache key differentiation for user sessions
  • Handles session changes (login/logout)

Registers Stimulus controllers:

  • Lazy-loads controllers from app/javascript/controllers
  • Handles controller namespacing

Initializes Bootstrap components:

  • Popovers with sanitization
  • Modals
  • Lightbox (@fancyapps/ui Fancybox)
  • Re-initializes on Turbo navigation

Manages CSRF tokens:

  • Updates tokens from globals.json
  • Sets up Turbo CSRF integration

International phone input formatting:

  • Initializes intl-tel-input library
  • Re-initializes on Turbo navigation
  • Handles hidden field sync

HLS/DASH video playback (Shaka Player) is initialized solely by the Stimulus video-player controller (app/javascript/controllers/video_player_controller.js), attached to every player <video> via data-controller="video-player". It picks the core build or the Shaka-UI build (controls + chapter markers) based on data-video-player-shaka-ui-value. There is no separate setup/video.js auto-scanner — it was removed because it raced the controller and broke the watch-page UI player.

Declarative feature loading:

  • Reads window.features or data-features attributes
  • Dynamically imports feature modules

Core application setup:

  • Phone tracking (CallRail)
  • Mobile detection
  • Legacy wwwAppInit() integration

React apps use a WeakMap pattern to prevent createRoot warnings during Turbo navigation:

const reactRoots = new WeakMap();
function mount(element) {
if (reactRoots.has(element)) {
return reactRoots.get(element);
}
const root = createRoot(element);
reactRoots.set(element, root);
return root;
}

All JavaScript is Turbo-aware:

  • Event handlers use turbo:load instead of DOMContentLoaded
  • Components re-initialize on navigation
  • State resets on cache restoration

For backward compatibility, some functions are exported to window:

window.app = app;
window.mobileCheck = mobileCheck;
window.contactFormInit = contactFormInit;
window.isMobile = mobileCheck();
  1. Stimulus Controller: Preferred for DOM interactions

    app/javascript/controllers/my_feature_controller.js
    import { Controller } from "@hotwired/stimulus"
    export default class extends Controller {
    connect() { /* ... */ }
    }
  2. Setup Module: For global initialization

    client/js/www/setup/my_feature.js
    export function initMyFeature() { /* ... */ }

    Then import in www.index.js

  3. React App: For complex interactive features

    client/js/www/my_feature/myFeature.index.js
    import { createRoot } from 'react-dom/client';

jQuery and Rails UJS have been fully removed. All code uses:

  • Stimulus controllers for DOM interactions
  • Vanilla JS for simple cases
  • Native fetch for AJAX

Legacy RJS responses are being replaced with:

  • Turbo Streams for partial updates
  • Turbo Frame responses
  • JSON API responses