Generative slime-mold art in WebGPU. 19 presets, audio-reactive routing across 10 targets, kaleidoscope, paint/glow blend modes, long-exposure trails. PWA + standalone macOS app. https://jkaindl.codeberg.page/physarum/
  • Swift 56.7%
  • TypeScript 30.7%
  • Shell 4.9%
  • Metal 3.4%
  • WGSL 2.1%
  • Other 2.2%
Find a file
Johannes Kaindl 3b974c1d0f
docs(readme): Physarum Ambient is on the App Store, not heading to it
The app has been live since 2026-06-24 (iPhone, iPad, Apple TV), but the
README still announced it as "heading to the App Store" — so the one place a
visitor looks first has been wrong for three weeks, and the store link existed
nowhere in this repo.

- Link the App Store listing in the Native apps section
- Add an App Store badge to the header row

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 14:56:12 +02:00
.forgejo/workflows build(player): publish bundle in deploy; document embedding 2026-05-28 13:54:04 +02:00
.gitea/issue_template chore(repo): add SECURITY, .gitea issue templates, .editorconfig 2026-05-27 13:40:54 +02:00
.github chore: add Liberapay funding + commercial-license contact; public email -> code@jkaindl.de 2026-05-30 19:48:49 +02:00
apple chore(appstore): UI-in-use screenshots + preview videos for 4.2/2.3.3 re-review 2026-06-26 14:08:48 +02:00
assets chore(presets): prune classic thumbnails to the 7 curated 2026-06-21 15:35:08 +02:00
docs fix(appstore): add silent AAC track to preview videos (ASC audio validator) 2026-06-26 14:57:49 +02:00
macos docs(macos): document native-app DMG (macOS 14+, Metal) for 2.0.0 2026-06-15 22:23:46 +02:00
public fix(tvos): Top Shelf preview video as HLS (m3u8) — .mp4 didn't autoplay 2026-06-21 22:32:58 +02:00
scripts fix(appstore): add silent AAC track to preview videos (ASC audio validator) 2026-06-26 14:57:49 +02:00
seeds docs(seeds): fix-seed — embed navigateFallback serves app-shell at default preset 2026-06-20 21:51:06 +02:00
src feat(presets): retire the hand-built classics — library is the 7 curated 2026-06-21 15:22:18 +02:00
tests feat(presets): retire the hand-built classics — library is the 7 curated 2026-06-21 15:22:18 +02:00
.editorconfig chore(repo): add SECURITY, .gitea issue templates, .editorconfig 2026-05-27 13:40:54 +02:00
.gitignore feat(appstore): clean full-screen stills for all 7 presets (iOS/iPad/tvOS) 2026-06-22 11:24:02 +02:00
.nvmrc chore: initial gitignore + node version pin 2026-05-21 00:27:54 +02:00
biome.json chore: biome config for lint + format 2026-05-21 00:29:42 +02:00
CHANGELOG.md chore(release): v2.3.0 — a11y + error-handling, App Store readiness, tvOS Top Shelf, unified icon 2026-06-22 09:38:57 +02:00
CLA.md docs: dual-license model + contributor license agreement 2026-05-30 14:07:57 +02:00
CONTRIBUTING.md docs: dual-license model + contributor license agreement 2026-05-30 14:07:57 +02:00
index.html feat(mobile): iOS PWA polish — safe-areas, overflow, dvh, touch tuning 2026-05-24 21:49:12 +02:00
lefthook.yml chore: lefthook pre-commit hooks (biome + tsc) 2026-05-21 00:30:13 +02:00
LICENSE chore: add AGPL-3.0 license 2026-05-21 00:28:02 +02:00
LICENSING.md chore: add Liberapay funding + commercial-license contact; public email -> code@jkaindl.de 2026-05-30 19:48:49 +02:00
package-lock.json feat(presets): pre-baked thumbnails + paint-mode fix for dark inks 2026-05-25 09:30:16 +02:00
package.json chore(release): v2.3.0 — a11y + error-handling, App Store readiness, tvOS Top Shelf, unified icon 2026-06-22 09:38:57 +02:00
player.html feat(player): embed route (player.html) via multi-page build 2026-05-28 13:44:37 +02:00
playwright.config.ts test(e2e): Slice 1 smoke tests (load + L/E/C hotkeys) 2026-05-21 12:39:53 +02:00
README.md docs(readme): Physarum Ambient is on the App Store, not heading to it 2026-07-16 14:56:12 +02:00
SECURITY.md feat(macos): Developer ID signing + notarization — release 1.4.1 2026-06-01 17:04:29 +02:00
tsconfig.json chore: strict tsconfig with Solid JSX + WebGPU types 2026-05-21 00:28:59 +02:00
vite.config.ts feat(player): embed route (player.html) via multi-page build 2026-05-28 13:44:37 +02:00
vite.element.config.ts build(player): standalone custom-element library bundle 2026-05-28 13:45:25 +02:00
vitest.config.ts chore(test): use solid-js client build + entstale version e2e 2026-05-25 00:13:47 +02:00

Physarum

Pure ambient generative art — a stigmergy simulation in WebGPU.

License: AGPL-3.0 Latest release Built with WebGPU On the App Store

Physarum simulates Physarum polycephalum (slime mold) — thousands of agents follow chemical trails, forming organic, ever-shifting path networks. It runs as a web app, a native macOS app, and native apps for iPhone, iPad, and Apple TV. Watch, tune, record, share.

Physarum — Mystic preset

Download for macOS    Launch the web app

macOS app requires macOS 14+ (native Metal, universal) · the web app runs in any WebGPU browser

macOS: the release app is Developer ID-signed and Apple-notarised, so it launches straight away — no Gatekeeper detour. Background and the build/signing details: docs/MACOS-APP.md.

Features

  • 3-species stigmergy with a per-pair interaction matrix — each species reads three pheromone channels and steers via a 3-sensor classical Physarum (M1) model.
  • 7 curated factory presets — Aurora, Mandala, Mystic, Terminal Haze, Neon Waves, Solar Veil, and Dancing Ink: a hand-tuned starting set spanning luminous rings, kaleidoscopic symmetry, and ink-on-paper.
  • Live editor with collapsible sections, per-parameter help tooltips, per-section reset, and a save-as-new flow with auto-baked thumbnails.
  • Audio-reactive — microphone or tab-audio capture, free routing from bass/mid/high to any of 10 modulation targets (move, turn, deposit, sensor, rhythm, chaos, exposure, bloom, saturation, contrast), with auto-gain.
  • Capture — PNG screenshot, WebM/MP4 video recording, msgpack- packed #p=… share links.
  • Post-processing stack — HDR feedback echo, threshold bloom, ACES tonemap, saturation/contrast/vignette grading.
  • Two blend modes — additive (glow) for dark backgrounds, paint (ink) for bright ones.
  • Kaleidoscope (1-6 mirror axes) and long-exposure head highlight for two distinct post-fx looks.
  • Sim-speed multiplier (1-8×) to evolve patterns faster than real time.

The curated factory set — seven hand-tuned presets that ship as the starting slots in the native apps (new in v2.1.0). Click any preset for a live, full-window demo (then the ⛶ button for true fullscreen). These 7 are the full built-in set.

Aurora
Aurora
luminous magenta ring
▶ live demo
Mandala
Mandala
8-fold star kaleidoscope
▶ live demo
Mystic
Mystic
violet chase kaleidoscope
▶ live demo
Terminal Haze
Terminal Haze
phosphor-green kaleidoscope
▶ live demo
Neon Waves
Neon Waves
electric neon ribbons
▶ live demo
Solar Veil
Solar Veil
molten amber veil
▶ live demo
Dancing Ink
Dancing Ink
red ink on paper
▶ live demo

Native apps

Beyond the web app, Physarum ships as native SwiftUI/Metal apps — the same engine, with a full authoring editor, audio-reactivity, and capture on every platform:

  • macOS — download the notarised universal app below (macOS 14+).
  • iPhone, iPad & Apple TVon the App Store as Physarum Ambient, free. On Apple TV, Physarum becomes a lean-back ambient display you steer from the couch or mirror live from your phone.
Physarum on iPhone
iPhone
Physarum on iPad
iPad

Physarum on Apple TV — ambient mode
Apple TV — ambient mode · ▶ watch a 25 s preview

Embed

Drop the player onto any page with the <physarum-player> custom element:

<script type="module" src="https://jkaindl.codeberg.page/physarum/physarum-player.js"></script>

<!-- a built-in preset -->
<physarum-player preset="builtin:aurora"></physarum-player>

<!-- your own preset: in the app, open Settings -> "Copy embed code" -->
<physarum-player preset="token:..."></physarum-player>

<!-- a cycling playlist -->
<physarum-player playlist="builtin:aurora,builtin:mandala,builtin:mystic" interval="20"></physarum-player>

Attributes: preset, playlist, interval (seconds), controls (auto/always/none), poster, asset-base, autoplay, loop. JS API: .play(), .pause(), .next(), .prev(), .load(source). Events: physarum:ready, physarum:presetchange, physarum:error.

The player is purely visual (no audio reactivity) and falls back to a poster image when WebGPU is unavailable. Or embed via iframe using the hosted route:

<iframe src="https://jkaindl.codeberg.page/physarum/player.html?preset=builtin:aurora"
        style="border:0;width:100%;height:400px" allowfullscreen allow="fullscreen"></iframe>

Requirements

  • Browser with WebGPU support (Chrome/Edge 113+, Safari 26+, Firefox stable)
  • For audio-reactive mode: microphone permission
  • Node 22+ for development

Development

npm install
npm run dev

Visit http://localhost:5173.

Build

npm run build
npm run preview

Testing

npm test          # unit tests
npm run test:e2e  # end-to-end (Playwright)
npm run lint
npm run typecheck

Preset thumbnails

Built-in preset cards ship with pre-rendered thumbnails in public/preset-thumbs/. After editing a preset's parameters, re-bake:

npm run dev                # in one terminal
npm run bake:thumbnails    # in another — opens a headed Chromium

Headed mode is required on macOS — Chrome's headless renderer doesn't expose a working WebGPU device, so headless captures end up blank.

Distribution

Web (PWA) — every push to main is built and published to Codeberg Pages by .forgejo/workflows/deploy.yml: https://jkaindl.codeberg.page/physarum/

macOS app — the native SwiftUI/Metal app (full authoring editor, audio-reactive, capture/export), Developer ID-signed + notarised, universal (Apple Silicon + Intel):

./scripts/build-macos-app.sh   # → dist-macos/Physarum.dmg

See docs/MACOS-APP.md. App icons are generated from assets/icon.svg via ./scripts/gen-icons.sh.

Contributing

Contributions are welcome — see CONTRIBUTING.md. Release history is in CHANGELOG.md.

License

Physarum is dual-licensed:

  • AGPL-3.0-or-later for open-source use — see LICENSE.
  • A commercial license is available for proprietary use that the AGPL doesn't allow — e.g. embedding the <physarum-player> component on a closed-source website or in a SaaS — see LICENSING.md or email code@jkaindl.de.

Contributions are accepted under the Contributor License Agreement.

Support

If Physarum brightens a screen of yours, you can leave a tip on Liberapay. For commercial use, see LICENSING.md.