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.
<!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>