Release Cadence

The Yearly Major Version and Weekly npm Patch Cadence

Since version 5.0, Babylon.js 89,603 publishes a minor version every Thursday and a patch during the week when a fix cannot wait. Older minors are never patched, the public API does not break between minors, and breaking changes wait for the yearly major: 7.0 on 28 March 2024, 8.0 on 27 March 2025, 9.0 on 26 March 2026. The registry (npm 2,036 view @babylonjs/core time) shows the rhythm: 9.26.0, 9.27.0 and 9.28.0 landed on the Thursdays 10, 17 and 24 September 2026, with patches 9.26.1, 9.26.2 and 9.27.1 in between, and version 9 reached 58 releases in 26 weeks. Every first-party package (@babylonjs/gui, loaders, inspector...) is republished with the same number, so keep them all on one version, with a caret range such as "^9.28.0" as the documentation recommends. Three.js 30,815 (Releases and Versions) ships an rNNN release every few weeks, any of which may carry breaking changes, so Three.js projects pin exact versions.

September 2026 as a 3D calendar: a minor release every Thursday, patches in betweenHTMLLive
<!doctype html>
<style>
  body { margin: 0; background: #f7f3ec; }
  canvas { width: 100%; max-width: 600px; height: 400px; display: block; touch-action: none; }
</style>
<canvas id="view"></canvas>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babylonjs-gui@9.28.0/babylon.gui.min.js"></script>
<script>
const canvas = document.getElementById('view');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = BABYLON.Color4.FromHexString('#f7f3ecff');
const camera = new BABYLON.ArcRotateCamera('cam', -Math.PI / 2, 0.42, 10.5,
  new BABYLON.Vector3(0, 0, -0.1), scene);
camera.attachControl(canvas, true);
new BABYLON.HemisphericLight('sky', new BABYLON.Vector3(0.3, 1, -0.5), scene);
const ui = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI('ui');

// Releases of @babylonjs/core in September 2026 (day of month -> version)
const MINORS = { 10: '9.26.0', 17: '9.27.0', 24: '9.28.0' };   // Thursdays
const PATCHES = { 14: '9.26.1', 15: '9.26.2', 21: '9.27.1' };  // when a fix cannot wait
const FIRST_WEEKDAY = 1;                              // 1 Sep 2026 is a Tuesday (Mon = 0)

const mat = (hex) => {
  const m = new BABYLON.StandardMaterial(hex, scene);
  m.diffuseColor = BABYLON.Color3.FromHexString(hex);
  m.specularColor = BABYLON.Color3.Black();
  return m;
};
const tileMat = mat('#fffaf0'), thursdayMat = mat('#e3ecf5');
const minorMat = mat('#1f5f8b'), patchMat = mat('#e09a10');

['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].forEach((name, col) => {
  const plane = BABYLON.MeshBuilder.CreatePlane(name, { size: 0.01 }, scene);
  plane.position.set((col - 3) * 1.25, 0, 3.4);
  label(plane, name, col === 3 ? '#1f5f8b' : '#777', 0);
});

for (let day = 1; day <= 30; day++) {
  const cell = day - 1 + FIRST_WEEKDAY;
  const col = cell % 7, row = Math.floor(cell / 7);
  const x = (col - 3) * 1.25, z = 2.5 - row * 1.25;
  const tile = BABYLON.MeshBuilder.CreateBox('day' + day, { width: 1.15, height: 0.1, depth: 1.15 }, scene);
  tile.position.set(x, 0, z);
  tile.material = col === 3 ? thursdayMat : tileMat;
  const version = MINORS[day] || PATCHES[day];
  const corner = new BABYLON.TransformNode('corner' + day, scene);   // top-left of the tile
  corner.position.set(x - 0.38, 0.05, z + 0.38);
  label(corner, String(day), '#999', 0);
  if (!version) continue;
  const height = MINORS[day] ? 0.9 : 0.4;
  const bar = BABYLON.MeshBuilder.CreateCylinder(version, { height, diameter: 0.45 }, scene);
  bar.position.set(x, height / 2 + 0.05, z);
  bar.material = MINORS[day] ? minorMat : patchMat;
  label(bar, version, MINORS[day] ? '#1f5f8b' : '#a86d00', -height * 16 - 12);
}

const header = new BABYLON.GUI.TextBlock('h',
  'Majors once a year: 7.0 (Mar 2024) · 8.0 (Mar 2025) · 9.0 (26 Mar 2026)\n' +
  'Version 9: 58 releases in 26 weeks — keep every package on one version, "^9.28.0"');
Object.assign(header, { fontSize: 13, color: '#333', height: '44px', top: '6px',
  verticalAlignment: BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP });
ui.addControl(header);

function label(mesh, text, color, offsetY) {
  const block = new BABYLON.GUI.TextBlock('', text);
  Object.assign(block, { color, fontSize: 12, fontWeight: 'bold',
    resizeToFit: true, outlineWidth: 3, outlineColor: '#f7f3ec' });
  ui.addControl(block);
  block.linkWithMesh(mesh);
  block.linkOffsetY = offsetY;
}

engine.runRenderLoop(() => scene.render());
addEventListener('resize', () => engine.resize());
</script>