WWW JavaScript Architecture
This document describes the organization and architecture of the WWW JavaScript codebase.
Directory Structure
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
Entry Point: www.index.js
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';
Setup Modules
turbo.js
Configures Turbo Drive for SPA-like navigation:
- Enables Turbo Drive
- Sets up cache key differentiation for user sessions
- Handles session changes (login/logout)
stimulus.js
Registers Stimulus controllers:
- Lazy-loads controllers from
app/javascript/controllers - Handles controller namespacing
bootstrap.js
Initializes Bootstrap components:
- Popovers with sanitization
- Modals
- Lightbox (@fancyapps/ui Fancybox)
- Re-initializes on Turbo navigation
csrf.js
Manages CSRF tokens:
- Updates tokens from
globals.json - Sets up Turbo CSRF integration
intl_tel_input.js
International phone input formatting:
- Initializes
intl-tel-inputlibrary - Re-initializes on Turbo navigation
- Handles hidden field sync
Video players
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.
features.js
Declarative feature loading:
- Reads
window.featuresordata-featuresattributes - Dynamically imports feature modules
app_init.js
Core application setup:
- Phone tracking (CallRail)
- Mobile detection
- Legacy
wwwAppInit()integration
React Applications
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;
}
Turbo Integration
All JavaScript is Turbo-aware:
- Event handlers use
turbo:loadinstead ofDOMContentLoaded - Components re-initialize on navigation
- State resets on cache restoration
Global Exports
For backward compatibility, some functions are exported to window:
window.app = app;
window.mobileCheck = mobileCheck;
window.contactFormInit = contactFormInit;
window.isMobile = mobileCheck();
Adding New Features
-
Stimulus Controller: Preferred for DOM interactions
// app/javascript/controllers/my_feature_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { /* ... */ } } -
Setup Module: For global initialization
// client/js/www/setup/my_feature.js export function initMyFeature() { /* ... */ }Then import in
www.index.js -
React App: For complex interactive features
// client/js/www/my_feature/myFeature.index.js import { createRoot } from 'react-dom/client';
Architecture Notes
No jQuery or Rails UJS
jQuery and Rails UJS have been fully removed. All code uses:
- Stimulus controllers for DOM interactions
- Vanilla JS for simple cases
- Native
fetchfor AJAX
RJS (.js.erb files)
Legacy RJS responses are being replaced with:
- Turbo Streams for partial updates
- Turbo Frame responses
- JSON API responses