SAM.

THE GARAGE / YOUR CODE ON TOP

One visual layer.
Your logbook.

The car, bonnet animation, camera moves and highlights live in assets/garage.js and assets/garage.css. The example landing page and its sample content live separately in demo.js and site.css. No build step, account, database or connection to an ECU is required.

Download HTML + CSS + JS ↓

Open the background-only demo ↗ · Open the clean embed ↗

Drop it into an existing page

Copy assets/ into your site and keep its structure. Put your existing interface above the background. Vendor scripts are included locally; no external CDN is needed.

<link rel="stylesheet" href="/assets/garage.css">
<div id="sam-background" class="sam-garage"></div>
<main id="my-logbook">
  <!-- Your existing text and tabs -->
</main>
<style>
  #sam-background { position: fixed; inset: 0; z-index: 0; }
  #my-logbook { position: relative; z-index: 1; }
</style>
<script type="module">
  import { mountGarage } from '/assets/garage.js';
  const garage = mountGarage(document.querySelector('#sam-background'));
  // Connect your own existing tabs:
  document.querySelector('#your-ignition-tab')
    .addEventListener('click', () => garage.focus('ignition'));
</script>

Camera and animation hooks

garage.focus('garage');   // Hero image, bonnet closed
garage.focus('engine');   // Open bonnet, engine overview
garage.focus('boost');    // Intercooler / supercharger region
garage.focus('ignition'); // Coil pack and HT leads
garage.focus('fuel');     // Fuel rail / injector region
garage.focus('cooling');  // Radiator / coolant region
garage.focus('ecu');      // ECU enclosure beside the airbox
garage.setBonnet(true);   // Open or close the bonnet
garage.setRotate(true);   // Orbit the 3D MINI
garage.setPaused(true);   // Pause orbit and highlight pulses
garage.replay();          // Replay the brief arrival
garage.getState();        // Read the visual state
garage.destroy();         // Remove / dispose when unmounting

mountGarage(target, { intro: false, reducedMotion: true, onFocus, onReady, onError }) also accepts callbacks and motion preferences. The visitor’s reduced motion setting is respected automatically. Edit SYSTEMS at the top of garage.js to adjust camera positions and highlight labels. Highlight geometry is in makeEngine().

Or use an iframe

<iframe src="/embed.html" title="Sam’s MINI engine explorer"
  style="position:fixed;inset:0;width:100%;height:100%;border:0"
></iframe>

The clean embed accepts a same-origin message, so existing tabs can control it without replacing their own behaviour:

const frame = document.querySelector('iframe');
frame.contentWindow.postMessage(
  { type: 'sam-garage:focus', system: 'ignition' },
  location.origin
);

Same-origin integration is the default. Set data-parent-origin on the embed’s garage element to one specific trusted origin for a deliberately cross-origin embed. Wildcard message origins are rejected. An iframe behind content may need pointer-events:none if the parent should receive all clicks.

Keep the credits with the model

The MINI model by cenobyte is used under CC BY 4.0. Keep the model credit and licence link visible somewhere on the final site. The engine is an illustrated W11 layout, not a service diagram. Sample logs and example issues can be replaced entirely by the existing logger.

← Back to Sam’s garage