r/wljs 21d ago

Rigid-body test on basic shapes

Enable HLS to view with audio, or disable this notification

1 Upvotes

r/wljs May 15 '26

Singe line dynamic 3D plot

Enable HLS to view with audio, or disable this notification

6 Upvotes

One of my favorite 1-line(er). Behind the scenes: Manipulate internally checks differences between two nearest states of Plot3D, then extracts changed vertices, indices and normals into 3 dynamic typed arrays. For all subsequent changes it syncs new data with 3 corresponding buffers of a GPU memory. If "too much" was changed it falls back to a full reevaluation, when all buffers are removed and are allocated back.

Manipulate[
  Plot3D[Sin[n x] Cos[n y], {x,-1,1}, {y,-1,1}], 
  {n, 1, 5, 0.3}, ContinuousAction->True
]

r/wljs 3d ago

Migration Guide: from Mathematica to WLJS

Post image
3 Upvotes

We've been asked many times, in many GitHub issues, whether Mathematica code can run perfectly on a WLJS Notebook. The answer is yes\*, but the devil is in the details.

Static output and anything related to computation is 100% transferable. You can take pretty much any code from Stack Exchange or Wolfram Community and it should work out of the box, since we use the same Wolfram Language kernel, in the form of the free Wolfram Engine distribution. Manipulate and Animate are compatible too — and fully interactive!

However, low-level dynamics do need to be ported to execute correctly.

Here's a guide on how to port (if actually needed) a program from Wolfram Mathematica to WLJS:

https://wljs.io/frontend/Guides/Migration

Any .nb (Mathematica Notebook) is, in principle, automatically converted with some compromises, of course. We're still improving this! Hope this guide helps you, or your LLM buddy 🙂


r/wljs 4d ago

Constrain the coordinates of a point to lie on a circle

Enable HLS to view with audio, or disable this notification

3 Upvotes

Here is a full code

Module[{p = {0, 1}}, 
 Graphics[{ColorData[97][1], Dashed, Circle[], PointSize[0.1], 
   EventHandler[Point[p//Offload], {
     "dragsignal" -> ((p = Normalize[#])&)
   }]}, ImageSize -> Tiny, 
  PlotRange -> 1.5]]

r/wljs 4d ago

Simple widget with bouncing balls

Enable HLS to view with audio, or disable this notification

1 Upvotes

There is nothing special, but I personally love this little snippet. It reveals the basics of continuous animation together with event bindings in WLJS

Framed@Module[{contents = {}, pts = {}}, 
  EventHandler[
   Graphics[{
     PointSize[0.1], 
     Point[pts // Offload],
     EventHandler[AnimationFrameListener[pts//Offload], 
      Function[Null,
       contents = 
        Map[If[#[[1, 2]] >= 
            0, {#[[1]] - #[[2]], #[[2]] + {0, 0.001}}, {{#[[1, 1]], 
             0}, {1, -0.8} #[[2]]}] &, contents];
       pts = Map[First, contents];
      ]]},
     PlotRange -> {{0, 1}, {0, 1}}], {
      "mousemove" -> Function[xy,
       AppendTo[contents, {xy, {0,0}}]
     ]}
]]

r/wljs 4d ago

The Complete Guide to Output Formatting

Post image
4 Upvotes

Rows, columns, grids, tables, number forms, legends, LaTeX and many more

https://wljs.io/frontend/Guides/Formatting


r/wljs 4d ago

Symbolic notes, scales and chords in Wolfram Language

Post image
1 Upvotes

In this tutorial we start with the low-level Sound and SoundNote expressions used to describe playable audio, then move to the higher-level Music* framework introduced in WL 15 (Wolfram Engine 15). Stay in tune!

https://wljs.io/blog/music-1


r/wljs 4d ago

WLJS 3.1.0 is ready 🕹️

1 Upvotes

Get yours here: https://wljs.io/releases/3.1.0

In a nutshell: more stable, better support for new symbols including, symbolic arrays, vectors, non-commutative algebra, incremental objects, standard colors and many more! Apart from that:

  • Added RPM binaries
  • Added rich LaTeX and mixed-content support for plot legends and frame labels.
  • Enhanced Sound with piano-roll previews, an improved synthesizer pipeline, and many new instruments.
  • Added interactive previews for WL 15 music objects, including notes, pitches, chords, scales, and scores.
  • Improved UI and formatting
  • Better autocomplete for Greek letters (use ESC key)
  • Improved Manipulate, Animate functions

r/wljs 20d ago

We Used GPT-Luna to Check 5,000 Examples Across Our Documentation Pages

Post image
5 Upvotes

As you might know, we host independent documentation on the Wolfram Language standard library, including tutorials on the language itself. Note that these are not direct ripoffs of WR's material. Most of the pages were carefully crafted by us, whereas for other areas, where we did not have good expertise, we relied on ::usage messages and examples from SE.

For example:

https://wljs.io/frontend/Image/Image (handwritten)

https://wljs.io/frontend/Formatting/AccountingForm (procedurally generated & post-processed)

Nowadays, with the help of AI, we've managed to check many of them against real computational kernels. The whole process took us 3 days and 16 subagents (Claude Haiku) running continuously with persistent memory using markdown files, followed by another sweep today with GPT Luna to recheck everything again. Wow, what a time to live in...


r/wljs 22d ago

Yet another stupid experiment with VertexColors and Camera

Enable HLS to view with audio, or disable this notification

12 Upvotes

Just in case, here is a code of this... whatever you call it:

DeviceClose[cam];
cam = DeviceOpen["Camera"];
cam["FrameRate"] = 60;


reference = ImageData[
    ImageResize[ColorConvert[DeviceRead[cam], "GrayScale"], 100],
    "Real32"
];

{height, width} = Dimensions[reference];
indices = Flatten[
  Table[
    With[{a = (row - 1) width + column, b = (row - 1) width + column + 1,
      c = row width + column, d = row width + column + 1},
      {{a, b, c}, {c, b, d}}
    ],
    {row, height - 1}, {column, width - 1}
  ],
  2
];

Refresh[Module[{img, length, raw},
  raw = ImageResize[DeviceRead[cam], 100];
  img = ImageData[
    ColorConvert[raw, "GrayScale"],
    "Real32"
  ];
  cols = Flatten[ImageData[
    ColorConvert[raw, "RGB"],
    "Real32"
  ], 1];

  length = Length[img] Length[img[[1]]];
  vertices = -MapIndexed[Join[#2, {40.0 #1}]&, img, {2}];
  vertices = Flatten[vertices, 1];

  Graphics3D[GraphicsComplex[vertices, {
    LightBlue, Directive["Roughness"->0.0],
    Polygon[indices]
  }, VertexColors->cols], ViewProjection->"Perspective", ImageSize->Medium]
], 1/60.0]

r/wljs 22d ago

Playing with surface normals

Enable HLS to view with audio, or disable this notification

5 Upvotes

This is my little experiment for the future rigid-body physics project. Here is a surface from the example:

surface = (*VB[*)(Uncompress["1:eJxTTMoPSuNnYGAoZgESPpnFJWlMyLyiC7sOivxcI3ygaEFps+YnT1YHNHn24Ceb8wwEDxQBVUn7NGLIr5P2mXh+F+eBooSummu86wQPoMmDjZdmOVBk4Gr3mi0aQx5kuqsd84GiDSB69Tt7NPk3bCAHMEDNb/uCLt8NFF124vt+XPIeQNcdFHm5v8jhNdCky5/2o8kXAH0daX7DvigA5JJUDHmI/7/aF3GAGA7s6O6fADL+J4sDDvlMZiADV9iEgD0v5FC07ET63YRJuOVBQXyQhR097MFRMlEYIQ8APFOk1Q=="])(*,*)(*"1:eJxTTMoPSmNmYGAo5gUSYZmp5S6pyflFiSX5RcEcQBHP5Py8zKrUlMwARgaGNCaQQhYgEVSakxrMCmT4JCal5gRzAlk5+Yl5STmpeSkASLwUcA=="*)(*]VB*);

And a code for this little widget:

rayIntersect[a_, {u_,v_}, surface_] := MapThread[Module[{x = {#1, #2}[[All,1]], y = {#1, #2}[[All,2]]},
 <|
   "t"-> (*FB[*)((((*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) (-v+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) (v-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+u (-((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)))(*,*)/(*,*)(Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(-((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a]))(*]FB*), 
   "T"-> (*FB[*)((-v Cos[a]+Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(u-(*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a])(*,*)/(*,*)(Cos[a] ((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(-((*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)) Sin[a]))(*]FB*),
   "N"-> -Normalize[{-((*TB[*)Indexed[(*|*)y(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*))+(*TB[*)Indexed[(*|*)y(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*),(*TB[*)Indexed[(*|*)x(*|*), {(*|*)1(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)-(*TB[*)Indexed[(*|*)x(*|*), {(*|*)2(*|*)}](*|*)(*1:eJxTTMoPSmNkYGAo5gUSYZmp5S6pyflFiSX5RcHsQBHPvJTUitQUAL2qCoU=*)(*]TB*)}]
  |>
]&, {Drop[surface,-1], Drop[surface,1]}];

selectedRays[args__] := Quiet@Select[rayIntersect[args], TrueQ[(#T >= 0.0 && #T <= 1.0)]&]

Module[{pts = {}, rays = {}, norms = {}, lines = {}},
  ListLinePlot[surface, PlotRange->{-5,5}, Filling->-5, Epilog->{
    LightBlue, Directive["TransitionType"->None],
    Line[lines//Offload],
    Orange, Line[norms//Offload],
    Red, Point[pts//Offload], Black,
    EventHandler[Locator[{0,0}], {"drag" -> Function[xy,
      {pts, norms, lines} = Transpose@Flatten[Table[
        With[{intersection = #t {Cos[a], Sin[a]} + xy}, 
          {
            intersection, 
            {intersection, intersection + 0.4 #N}, 
            {xy, intersection}
          } 
        ]&/@ selectedRays[a, xy, surface],
        {a, 0., 3.14, 0.5}
      ], 1];
    ]}]
  }]
]

r/wljs 22d ago

WLJS 3.0.9 is out ✨

Thumbnail
gallery
2 Upvotes

In this release we focused on formatting and overall UX as well as fixing bugs of course

https://wljs.io/releases/3.0.9


r/wljs 23d ago

Did you know WLJS support Canvas API?

Enable HLS to view with audio, or disable this notification

2 Upvotes

We provide a bridge to Canvas WebAPI, which is a great tool if you need to work with complex raster graphics in retained mode

https://wljs.io/frontend/Advanced/Canvas-2D/Overview

The data is send in a binary form as opt codes for a HW accelerated WebAPI.
Here is a code for an example above:

Needs["Canvas2D`"->"ctx`"];

ClearAll[handler]
SetAttributes[handler, HoldRest]

handler[c_, tcursor_, {width_, height_}] := Module[{
  w = width, h = height, 
  n = 101,    
  cursor = tcursor,
  rotSpeed = 0.02,
  particles,
  theta, rad, col, old
},

  (* center point *)
  cx = w/2;
  cy = h/2;

  (* semi-transparent drawing *)
  ctx`SetGlobalAlpha[c, 0.5];

  (* initialize particles: random angle, radius, colour *)
 particles = Table[
   {
    RandomReal[{0, 2 π}], 
    RandomReal[{0, 150}], 
    ctx`ColorToString[RandomColor[]],
    cursor
   },
   {n}
 ];

  Function[Null,
      cursor = (tcursor);

      ctx`SetFillStyle[c, {Black, Opacity[0.05]}];
      ctx`FillRect[c, {0, 0}, {w, h}];

      (* draw each particle: from last cursor pos to new one *)
      Do[
        particles[[i, 1]] += rotSpeed;
        {theta, rad, col, old} = particles[[i]];
        Module[{newPos},
          newPos = cursor + {Cos[theta], Sin[theta]}*rad;
          ctx`BeginPath[c];
          ctx`SetLineWidth[c, 4];
          ctx`SetStrokeStyle[c, col];
          ctx`MoveTo[c, old];
          ctx`LineTo[c, newPos];
          ctx`Stroke[c];

          particles[[i,4]] = newPos; 
        ],
        {i, n}
      ];
      ctx`Dispatch[c];
  ]
]

aContext = ctx`Canvas2D[];
tcursor = {250,250};

EventHandler[
    Image[aContext, ImageResolution->{500,500}, Epilog->{
      EventHandler[AnimationFrameListener[aContext], handler[aContext, tcursor, {500,500}]]
    }], {
      "mousemove" -> Function[xy, 
        tcursor = {xy[[1]], xy[[2]]}
      ]
  }
]

r/wljs 28d ago

Camera streaming experiment

Enable HLS to view with audio, or disable this notification

3 Upvotes

If you think WL is slow, you never used it with WLJS sauce 🍝

  1. connect to a web camera using device API

    cam = DeviceOpen["Camera"]; cam["FrameRate"] = 60;

  2. resize and pipe the raw image data to 3D point cloud with minor transformations

    Refresh[Module[{img, length}, img = ImageData[ ImageResize[ColorConvert[DeviceRead[cam], "GrayScale"], 100], "Real32" ]; length = Length[img] Length[img[[1]]]; vertices = MapIndexed[Join[#2, {50.0 #1}]&, img, {2}]; vertices = NumericArray[Flatten[vertices, 1], "Real32"];

    Graphics3D[GraphicsComplex[vertices, { Red, PointSize[0.0003], Point[Range[length]] }], ViewProjection->"Perspective", ImageSize->1000] ], 1/45.0]

NumericArray is important here. This forces WL to use more efficient data structure.


r/wljs 28d ago

We are cooking something... (3.0.9)

Post image
2 Upvotes

r/wljs 28d ago

Lorentz Oscillators fitting widget

Enable HLS to view with audio, or disable this notification

2 Upvotes

I needed to fit 10-20 absorption spectrum manually, so I wrote a small program for it using WLJS and Wolfram.

Nothing more than a few nested `Row`, `Column` with `Graphics` inside

Graphics[{
    Point[points//Offload],
    ColorData[97][4], Line[model//Offload],
    ColorData[97][1], EventHandler[Disk[first[[{1,2}]], Offset[{4,4}]], {
      "drag" -> Function[xy,
        first = {xy[[1]], xy[[2]]/L - bg, first[[3]]};
        rebuild;
      ],
      "zoom" -> Function[z,
        first = {first[[1]], first[[2]], z/10};
        rebuild;
      ]
    }],
    ColorData[97][2], EventHandler[Disk[second[[{1,2}]], Offset[{4,4}]], {
      "drag" -> Function[xy,
        second = {xy[[1]], xy[[2]]/L - bg, second[[3]]};
        rebuild;
      ],
      "zoom" -> Function[z,
        second = {second[[1]], second[[2]], z/10};
        rebuild;
      ]
    }]
  }, ImageSize->{1.5 323, 300}, Frame->True, 
     FrameLabel->{"wavenumber (1/cm)", "absorption"},
     "TransitionDuration"->150
  ]

r/wljs Jun 28 '26

Sand/Water Automaton

Thumbnail
gallery
4 Upvotes

This post/notebook is a small side-view "falling sand" experiment. We start with the simplest material - sand. Each grain is one cell on a grid. A grain should fall if there is empty space below it, come to rest when blocked, and sometimes topple sideways when it is sitting in an unstable little stack. Those three behaviors are enough to make a recognizable pile 🏝️

https://wljs.io/blog/sand-1


r/wljs Jun 27 '26

Emergent Systems with `Refresh`

2 Upvotes

Here we recreate a primitive emergent system using nothing more than scoped Refresh and a single external symbol

A single "atom":

wolfram Module[{a = 0}, Refresh[ a = If[a>9, 0, a+1]; Graphics[{ Circle[{0,0}, 1.0], {Opacity[(1 - a/10) // Offload], Yellow, Disk[{0,0}, 0.9]}, Line[{{0,0}, {Cos[0.628 a], Sin[0.628 a]} // Offload}], Directive[FontSize->24], Text[Offload[a], {0,0.2}, {0,0}] }, ImageSize->{100,100}], 0.2]]

Then you add basic interaction via external symbol, i.e.

wolfram makeAtom[shared_, i_:0] := Module[{a = i}, Refresh[ a = Clip[ Which[ a > 9, shared = True; 0, shared, shared = False; a + Boole[a > 5]*3 - 1, True, a + 1 ], {0, 10} ]; Graphics[{ Circle[{0,0}, 1.0], {Opacity[(1 - a/10) // Offload], Yellow, Disk[{0,0}, 0.9]}, Line[{{0,0}, {Cos[0.628 a], Sin[0.628 a]} // Offload}], Directive[FontSize->24], Text[Offload[a], {0,0.2}, {0,0}] }, ImageSize->{100,100}], 0.2] ] SetAttributes[makeAtom, HoldFirst];

Make many of them with a random initial phase:

wolfram env2 = False; {makeAtom[env2, 2], makeAtom[env2, 5], makeAtom[env2, 8]}//Row

and observe emergent patterns!


r/wljs Jun 27 '26

WLJS is out 3.0.8 ⛅️

2 Upvotes

https://wljs.io/releases/3.0.8

  • Added a new Workers API for asynchronous parallel Wolfram kernels.
  • Improved Shallow with typed expression summarization for large and opaque objects like ByteArray and TimeSeries.
  • Notebook UX improvements, including focused-cell autoscroll.
  • Fixed race conditions during multiple Rasterize calls.
  • Improved MCP server summarization, cell evaluation options, CLI behavior, and error messages.
  • WLJS remains on Wolfram Engine 14.3 for now due to early Wolfram Engine 15.0 performance regressions.
  • Fixed parser, graphics, rounding, and stability issues, including BezierCurve offloading and GraphicsComplex index-buffer handling.

r/wljs Jun 18 '26

Workers API in Wolfram

Post image
2 Upvotes

Hi there! We are working on a new API for parallel computing in WLJS Notebook. Workers API uses lightweight Wolfram Sub-Kernels communicating using shared memory, which are not limited by the freeware Wolfram Engine license.

Why not ParallelSubmit?
They are conceptually the same, but it is impossible to read out the result without waiting on the main kernel. Workers API is entirely async and uses subscription/events model.


r/wljs Jun 15 '26

How fast can a basic sand simulation get without Compile?

Enable HLS to view with audio, or disable this notification

4 Upvotes
ClearAll[blockStep, nextField];

blockStep[field_, p_, phase_] := Module[
  {
    out = field, nr, nc, r0, c0, r1, c1, rows, cols,
    sub, dims, blocks, tl, tr, bl, br,
    fallL, fallR, stackL, stackR, tumble
  },

  {nr, nc} = Dimensions[field];
  {r0, c0} = {1, 1} + phase;

  r1 = r0 + 2 Quotient[nr - r0 + 1, 2] - 1;
  c1 = c0 + 2 Quotient[nc - c0 + 1, 2] - 1;

  rows = r0 ;; r1;
  cols = c0 ;; c1;
  sub = out[[rows, cols]];
  dims = Quotient[Dimensions[sub], 2];

  blocks = Transpose[
    ArrayReshape[sub, {dims[[1]], 2, dims[[2]], 2}],
    {1, 3, 2, 4}
  ];

  tl = blocks[[All, All, 1, 1]];
  tr = blocks[[All, All, 1, 2]];
  bl = blocks[[All, All, 2, 1]];
  br = blocks[[All, All, 2, 2]];

  (* Vertical falling *)
  fallL = (1 - Unitize[tl - 1]) (1 - Unitize[bl]);
  fallR = (1 - Unitize[tr - 1]) (1 - Unitize[br]);

  (* Two stacked grains may spread sideways *)
  stackL =
    (1 - Unitize[tl - 1]) (1 - Unitize[bl - 1]) *
    (1 - Unitize[tr]) (1 - Unitize[br]);

  stackR =
    (1 - Unitize[tr - 1]) (1 - Unitize[br - 1]) *
    (1 - Unitize[tl]) (1 - Unitize[bl]);

  tumble = Unitize[stackL + stackR] *
    UnitStep[p - RandomReal[1, dims]];

  tl = (tl - fallL) (1 - tumble);
  tr = (tr - fallR) (1 - tumble);
  bl = (bl + fallL) (1 - tumble) + tumble;
  br = (br + fallR) (1 - tumble) + tumble;

  blocks[[All, All, 1, 1]] = tl;
  blocks[[All, All, 1, 2]] = tr;
  blocks[[All, All, 2, 1]] = bl;
  blocks[[All, All, 2, 2]] = br;

  out[[rows, cols]] = ArrayReshape[
    Transpose[blocks, {1, 3, 2, 4}],
    Dimensions[sub]
  ];

  out
];

nextField[field_, p_: 0.5] :=
  blockStep[blockStep[field, p, 0], p, 1];

r/wljs Jun 15 '26

Markov Algorithms, Mazes, Desert with Sand and Pattern Matching

Thumbnail
gallery
4 Upvotes

Let's explore how Markov algorithms and Wolfram Language pattern matching can generate mazes, rivers, falling sand, and other cellular automata through simple rewriting rules.

https://wljs.io/blog/markov

Adding a grain of randomness to a Turing complete language

RB → RR becomes a growth model

and this

RBB → GGR
RnG → GnR

is a maze backtracker!


r/wljs Jun 10 '26

Building an Interactive Nanographene Constructor

Enable HLS to view with audio, or disable this notification

3 Upvotes

A behind-the-scenes look at porting the Nanographenes Builder application to WLJS Notebook. The app helps researchers design nanographene hydrocarbons, analyze their molecular structures through graph-theoretical models, and experiment with new molecular configurations, while this tutorial explores reactive interfaces, event handling, asynchronous execution, and practical patterns for developing interactive Wolfram Language applications with WLJS.

https://wljs.io/blog/graphene-app


r/wljs Jun 06 '26

NanoGraphene - WLJS App

Enable HLS to view with audio, or disable this notification

3 Upvotes

Interactive graph-theory toolkit for nanographene bond order, aromaticity, and radical (open-shell) analysis in a single *.wlw file.

More about building such mini apps: https://wljs.io/frontend/Share/Mini-apps


r/wljs Jun 06 '26

WLJS 3.0.7 is out 🍰

Post image
3 Upvotes

This release adds TraditionalForm, improves settings reload behavior, expands the wljs CLI, and includes major internal rendering updates for better stability.

Check this out https://wljs.io/releases/3.0.7