Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cubit.js

A lightweight, dependency-free JavaScript engine for modeling, manipulating, and visualizing NxN Rubik's Cubes.

Cubit.js is a lightweight, dependency-free JavaScript/npm library for applying Rubik’s Cube scrambles, modeling NxN cube states, and generating framework-agnostic 2D cube net data. Built from the cube engine powering Cubit, an open-source speedcubing platform, and was later extracted into an independent package so other cubing projects can use the same engine.

API Reference · Cube Model · Visualization Guide · Contributing

Cubit.js V1 focuses on one job:

Scramble
   ↓
Cube State Engine
   ↓
Scrambled Cube State
   ↓
2D Net Data
   ↓
Your UI

The package contains zero runtime dependencies and does not depend on React, Vue, Canvas, SVG, or any other rendering framework.


Installation

npm install cubit.js

Cubit.js uses ES modules.

import {
  applyScramble,
  getNetData
} from 'cubit.js';

Quick Start

import { applyScramble, getNetData } from 'cubit.js';

const scramble = "R U R' U' F2 U2 R' U";

// Apply the scramble to a solved 3x3 cube
const state = applyScramble(scramble, '3x3');

// Convert the resulting cube state into visualization data
const net = getNetData(state);

console.log(state);
console.log(net);

That's the basic Cubit.js workflow:

"R U R' U'"
      ↓
applyScramble()
      ↓
CubeState
      ↓
getNetData()
      ↓
Renderable 2D Net Data

Features

  • Zero runtime dependencies
  • Pure JavaScript / ESM
  • Immutable cube-state transformations
  • 2x2, 3x3, 4x4 and 5x5 support
  • Standard face turns
  • Prime turns
  • Double turns
  • Wide moves
  • Multi-layer wide moves
  • WCA-style scramble notation parsing
  • Physically verified cube rotations
  • Framework-agnostic visualization data
  • Deterministic state transformations
  • Comprehensive physical-correctness tests

Cubit.js deliberately separates cube mathematics from rendering.

The package calculates the cube.

You decide how it looks.


Documentation

Cubit.js includes detailed documentation for developers who want to go beyond the quick-start examples or understand the engine internals.

Guide Description
API Reference Complete reference for the public Cubit.js API, including function signatures, parameters, return values, examples, and error behavior.
Cube Model & Mathematics Technical documentation for the cube-state representation, coordinate system, face orientation, rotation mathematics, layer semantics, and immutability model.
Visualization Guide Learn how to turn Cubit.js net data into a visual cube net using HTML/CSS, SVG, Canvas, React, Vue, or other rendering technologies.
Contributing Development setup, architecture guidelines, testing requirements, regression testing, and contribution workflow.

Where should I start?

If you simply want to use Cubit.js:

  1. Follow the Quick Start below.
  2. Read the API Reference for available functions.
  3. Read the Visualization Guide if you're building a cube visualizer.

If you're interested in how Cubit.js works internally, see Cube Model & Mathematics.

Most applications only need applyScramble() and getNetData() to get started.


Supported Cubes

Puzzle Supported
2x2
3x3
4x4
5x5

Example:

applyScramble(scramble, '2x2');
applyScramble(scramble, '3x3');
applyScramble(scramble, '4x4');
applyScramble(scramble, '5x5');

Cube Orientation

Cubit.js uses the following solved orientation:

Face Color Hex
U (Up) White #F8FAFC
D (Down) Yellow #FACC15
F (Front) Green #22C55E
B (Back) Blue #3B82F6
R (Right) Red #EF4444
L (Left) Orange #F97316

The canonical orientation is therefore:

        WHITE
          U

ORANGE   GREEN   RED   BLUE
   L       F      R      B

        YELLOW
          D

When comparing a Cubit.js state against a physical cube, use the same orientation.


Supported Move Notation

Standard turns

R L U D F B

Counter-clockwise / prime turns

R' L' U' D' F' B'

Double turns

R2 L2 U2 D2 F2 B2

Wide moves

Rw Uw Fw Lw Dw Bw

Lowercase wide notation is also supported:

r u f l d b

Multi-layer wide moves

Examples:

3Rw
3Rw'
3Fw2

API

applyScramble(scrambleInput, puzzleType?)

The primary Cubit.js API.

Creates a solved cube and applies the supplied scramble.

const state = applyScramble(
  "R U R' U'",
  "3x3"
);

Parameters

scrambleInput

A scramble string or parsed move array.

"R U R' U'"

puzzleType

Supported values:

2x2
3x3
4x4
5x5

Default:

3x3

Returns

A new CubeState.


createSolvedCube(puzzleType?)

Creates a solved cube.

import { createSolvedCube } from 'cubit.js';

const cube = createSolvedCube('3x3');

Example state:

{
  dimension: 3,

  U: [
    ['WHITE', 'WHITE', 'WHITE'],
    ['WHITE', 'WHITE', 'WHITE'],
    ['WHITE', 'WHITE', 'WHITE']
  ],

  D: [...],
  F: [...],
  B: [...],
  R: [...],
  L: [...]
}

Each face is represented as an N × N matrix.


parseScramble(scramble)

Parses scramble notation into structured move objects.

import { parseScramble } from 'cubit.js';

const moves = parseScramble(
  "R U R' U'"
);

console.log(moves);

A move follows this structure:

{
  raw: "R'",
  face: "R",
  amount: -1,
  depth: 1,
  isWide: false
}

parseMove(move)

Parses one move.

import { parseMove } from 'cubit.js';

const move = parseMove("3Fw2");

Result:

{
  raw: "3Fw2",
  face: "F",
  amount: 2,
  depth: 3,
  isWide: true
}

applyMove(cubeState, move)

Applies one parsed move to an existing cube state.

import {
  createSolvedCube,
  parseMove,
  applyMove
} from 'cubit.js';

const cube = createSolvedCube('3x3');

const move = parseMove('R');

const nextState = applyMove(cube, move);

Cubit.js transformations are immutable.

cube remains unchanged.


2D Visualization

Cubit.js does not force a rendering technology on applications.

Instead, it converts the mathematical cube state into simple JavaScript data.

import {
  applyScramble,
  getNetData
} from 'cubit.js';

const state = applyScramble(
  "R U R' U'",
  "3x3"
);

const net = getNetData(state);

The returned structure resembles:

{
  dimension: 3,

  netLayout: {
    U: [...],
    L: [...],
    F: [...],
    R: [...],
    B: [...],
    D: [...]
  },

  faces: [
    { face: 'U', grid: [...] },
    { face: 'L', grid: [...] },
    { face: 'F', grid: [...] },
    { face: 'R', grid: [...] },
    { face: 'B', grid: [...] },
    { face: 'D', grid: [...] }
  ]
}

Each sticker contains rendering information:

{
  colorKey: 'WHITE',
  hexColor: '#F8FAFC',
  face: 'U',
  row: 0,
  col: 0,
  id: 'U-0-0'
}

That means applications can render Cubit.js output using:

  • CSS Grid
  • HTML
  • Canvas
  • SVG
  • React
  • Vue
  • Svelte
  • mobile UI frameworks
  • custom graphics engines

without Cubit.js depending on any of them.


Rendering a Cube Net

The conventional unfolded layout is:

            ┌─────┐
            │  U  │
            └─────┘

┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│  L  │ │  F  │ │  R  │ │  B  │
└─────┘ └─────┘ └─────┘ └─────┘

            ┌─────┐
            │  D  │
            └─────┘

Cubit.js provides the sticker data for each of these faces.

The positioning and styling remain under the consumer's control.


Vanilla JavaScript Example

<div id="cube-net"></div>

<script type="module">
  import {
    applyScramble,
    getNetData
  } from 'cubit.js';

  const state = applyScramble(
    "R U R' U'",
    "3x3"
  );

  const net = getNetData(state);

  const container =
    document.getElementById('cube-net');

  net.faces.forEach(({ face, grid }) => {

    const faceElement =
      document.createElement('div');

    faceElement.dataset.face = face;

    faceElement.style.display = 'grid';

    faceElement.style.gridTemplateColumns =
      `repeat(${net.dimension}, 30px)`;

    grid.forEach(row => {

      row.forEach(sticker => {

        const element =
          document.createElement('div');

        element.style.width = '30px';
        element.style.height = '30px';

        element.style.backgroundColor =
          sticker.hexColor;

        faceElement.appendChild(element);
      });

    });

    container.appendChild(faceElement);
  });
</script>

This example intentionally keeps rendering simple.

A production application can position the six face elements into the standard unfolded cube-net layout using CSS Grid, Canvas, SVG, or another rendering system.


Validation

Cube states can be validated using:

import { validateCubeState } from 'cubit.js';

const valid = validateCubeState(state);

Cubit.js validates structural properties of the state before mathematical operations where appropriate.


Error Handling

Invalid developer input produces explicit errors rather than silently changing the requested operation.

Examples include:

createSolvedCube('7x7');
parseMove('X');
parseScramble('R U SOMETHING');

Invalid layer depths and malformed move notation are also rejected.


Scramble Generation

Cubit.js V1 does not generate scrambles.

It consumes them.

For example:

const scramble =
  "R U2 F' L2 D B2 R' U";

const state =
  applyScramble(scramble, '3x3');

Scrambles may come from:

  • a scramble generator
  • a competition-compatible scrambling system
  • user input
  • another cubing library
  • your own application

The architecture is intentionally:

Scramble Generator
       ↓
Scramble String
       ↓
    Cubit.js
       ↓
Cube State
       ↓
Net Data
       ↓
Application UI

This keeps the state engine independent from scramble-generation implementations.


Immutability

Cubit.js does not mutate the supplied cube state during transformations.

For example:

const solved =
  createSolvedCube('3x3');

const afterR =
  applyMove(
    solved,
    parseMove('R')
  );

solved remains unchanged.

This makes the engine suitable for state-management systems and reactive UI architectures.


Testing & Physical Correctness

Cube mathematics can easily pass algebraic tests while still representating physical rotations incorrectly.

For that reason, Cubit.js uses both mathematical invariant tests and physical-reference tests.

The suite includes:

  • solved-state verification
  • matrix rotation verification
  • M⁴ = Identity
  • move + inverse verification
  • double-turn verification
  • color conservation
  • odd-cube center stability
  • all 12 physical quarter turns
  • multi-move sequences
  • unique sticker permutation verification
  • regression scramble verification
  • multi-size verification
  • randomized scramble cross-validation against an independent cube representation

Run the suite with:

npm test

Architecture

Cubit.js is intentionally split into small independent modules:

src/
├── constants.js
├── engine.js
├── index.js
├── mapper.js
├── matrix.js
└── parser.js

Engine

Responsible for cube state and physical transformations.

Parser

Responsible for converting notation into move operations.

Matrix

Contains reusable matrix transformation utilities.

Mapper

Transforms mathematical state into visualization-friendly data.

Index

Defines the public package API.


Relationship to Cubit

Cubit.js was born inside Cubit, an open-source speedcubing platform.

Cubit required a cube visualizer capable of taking the exact scramble shown to a user, applying that scramble mathematically to a solved cube, and displaying the resulting physical state.

Instead of coupling that engine permanently to the Cubit application, the reusable cube mathematics and visualization-data layer were extracted into an independent package.

That became Cubit.js.

Cubit remains the product.

Cubit.js is the reusable cube engine that originated from it.

The package is maintained independently so it can be used by other timers, trainers, visualizers, educational tools, cubing applications, experiments, and developer projects.


Roadmap

V1 — Cube State & Visualization Engine

Current release.

  • Scramble parsing
  • Cube-state generation
  • Move application
  • 2x2–5x5 support
  • Wide moves
  • Multi-layer moves
  • 2D visualization data
  • Framework-independent API

V2 — Generation & Rendering

Planned areas include:

  • built-in scramble generation
  • higher-level visualization helpers
  • SVG output
  • Canvas rendering helpers
  • optional React components
  • possible Vue / Svelte integrations
  • visualization customization

V3 — Solving & Analysis

Longer-term exploration includes:

  • solution generation
  • scramble analysis
  • move-sequence analysis
  • move optimization
  • cube-solving utilities
  • training-oriented APIs

The roadmap is directional and may evolve as Cubit.js develops.


Contributing

Contributions, bug reports, test cases, and feature proposals are welcome.

If you discover a scramble that produces an incorrect physical state, please include:

  • puzzle size
  • scramble
  • expected state
  • actual state
  • reproduction steps

Physical correctness is treated as a core requirement of the project.


License

Cubit.js is released under the MIT License.

See LICENSE for details.


Cubit.js

Built from the cube engine behind Cubit.

Scramble → State → Visualize.

About

A lightweight, dependency-free JavaScript/npm library for applying Rubik’s Cube scrambles, modeling NxN cube states, and generating framework-agnostic 2D cube net data. Built from the cube engine powering Cubit.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages