WWW JavaScript Architecture
This document describes the organization and architecture of the WWW JavaScript codebase.
Directory Structure
Section titled “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 pointThe 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
Section titled “Setup Modules”turbo.js
Section titled “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
Section titled “stimulus.js”Registers Stimulus controllers:
- Lazy-loads controllers from
app/javascript/controllers - Handles controller namespacing
bootstrap.js
Section titled “bootstrap.js”Initializes Bootstrap components:
- Popovers with sanitization
- Modals
- Lightbox (@fancyapps/ui Fancybox)
- Re-initializes on Turbo navigation
csrf.js
Section titled “csrf.js”Manages CSRF tokens:
- Updates tokens from
globals.json - Sets up Turbo CSRF integration
intl_tel_input.js
Section titled “intl_tel_input.js”International phone input formatting:
- Initializes
intl-tel-inputlibrary - Re-initializes on Turbo navigation
- Handles hidden field sync
Video players
Section titled “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
Section titled “features.js”Declarative feature loading:
- Reads
window.featuresordata-featuresattributes - Dynamically imports feature modules
app_init.js
Section titled “app_init.js”Core application setup:
- Phone tracking (CallRail)
- Mobile detection
- Legacy
wwwAppInit()integration
React Applications
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Architecture Notes”No jQuery or Rails UJS
Section titled “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)
Section titled “RJS (.js.erb files)”Legacy RJS responses are being replaced with:
- Turbo Streams for partial updates
- Turbo Frame responses
- JSON API responses
Related Documentation
Section titled “Related Documentation”- Asset Build Workflow
- Stimulus Controllers
- Skills Index