# Ollin roadmap

Ollin is a creative-coding framework for Swift and Metal on Apple platforms. It aims for the ergonomics of p5.js on a core built to OPENRNDR's standard. This file is the running list of what is planned and what is being explored. If you want to help, it is a good place to start.

The guides in [`Docs/`](docs/index.md) explain how the framework works and the conventions behind it. For working code, browse [`Examples/`](examples/index.md).

## How to contribute

Here are a few things to know before you pick something up:

- Building and running needs macOS 26+ and a Metal-capable GPU. Nothing replaces the Swift toolchain and Metal, so changes are verified on a Mac.
- A new drawing feature is built on the typed core first (the `Drawer` and the value types). Then it gets the bare p5-style call as sugar. Anything the bare API can do, the core should also be able to do, with more control.
- A feature is not done until it has an example. Examples live in [`Examples/`](examples/index.md), one idea per sketch. CI compiles them, so they do not rot. Writing the example also checks the API, because an API that is awkward to write against probably needs work.
- The items under [Up next](#up-next) are the most self-contained, so they tend to make the best first contributions.
- Some sections carry a rough priority tag. The tag **Near-term** marks well-scoped items that make good next pickups. The tag **Later** marks bigger items that depend on earlier work. A section with no tag is substantial and wanted, but it is not the next thing to pick up. Speculative ideas live under [Further out / exploratory](#further-out-exploratory), and the platform-gated legs live under [On the horizon](#on-the-horizon).

If you come from p5.js or Processing, [the Guide's Appendix C](guide/c-comingfromp5.md) maps the API you already know onto Ollin, and [Appendix E](guide/e-comingfromopenframeworksandopenrndr.md) covers the big moves from openFrameworks and OPENRNDR. The page [`Docs/Swift.md`](docs/swift.md) covers just enough Swift to get productive.

## Toward 1.0

Ollin is pre-1.0, and the public API still changes freely. Semantic version tags and a changelog begin with `0.1.0`, so a SwiftPM project has a version to pin before the API settles. At major zero, a breaking change or a new feature bumps the minor, and a fix bumps the patch. A consumer pins `.upToNextMinor`, and each release names its breaking renames in its notes. Version 1.0.0 is the release where the API settles. From that point on, every public rename ships a deprecation shim, which is the migration discipline described in [`CLAUDE.md`](https://github.com/eaviles/Ollin/blob/main/CLAUDE.md). `Scripts/api-diff.sh` turns strict at that tag, and a public spelling gone with no deprecated twin fails preflight from then on. This section names what that release waits on, and only that. Everything else on this page stays open for work at any time. The release does not wait on that work, and that work does not wait for the release.

- **Stabilization.** The release waits on three things here. The first is a last naming sweep over the public API before the tag, read from the listings under [`API/`](https://github.com/eaviles/Ollin/tree/main/API), because the shim discipline locks the names in at the release; `Scripts/check-api-names.sh` holds the settled spelling rules against those listings on every change, and `Scripts/check-api-pages.sh` holds every name in them to having a page, so that sweep is a reading for meaning (a `factor` that is not a multiplier, a verb that says less than the call does) rather than for spelling or for coverage. The second is a test suite that is reliable end to end, with no flaky or machine-bound failures. The third is working down the hand-verification backlog, which is the features that still wait on eyes, ears, or hardware.

- **The release itself.** This is the release notes, the `1.0.0` tag, and a README presentation pass. The ecosystem legs that need a public repository (DocC, a Swift Package Index listing, the extension index) follow the release. They do not gate it.
- **What an open repository is expected to carry.** These are the surfaces a visitor sees beside the README. None of them can be set from a file. The first is the About description and topics. The second is a social-preview image; the card the website already serves, `Logo/ollin-social.png`, is the file to upload. The third is Discussions switched on, with a Show and tell category and a pinned welcome thread. The fourth is a logged-out check that the issues link and the install URL resolve. The domains are set here too. The canonical home the About field names is ollin.art, and ollin.run, ollin.live, and ollin.mov become permanent redirects to it. All of these are small, and they are cheaper to set before the first stranger arrives than after. See the [design notes](design-notes.md#opening-the-repository), which also cover what the README presentation pass has to decide.

## Up next

These are near-term, fairly self-contained pieces. Each one is small and well-scoped.

- **More SDF shapes, when a good fit appears.** A candidate is any canonical form parameterized by a size and a ratio or two. Such a shape drops into the instanced-SDF path as four small touch-points: a shape tag, a builder, a distance function, and a fragment case.

See the [design notes](design-notes.md#small-pieces).

## Generative geometry

This tier is a set of classic generative-art building blocks. Each one emits vector geometry (points, `Contour`s, `Shape`s) that feeds the existing draw, shape-boolean, hatching, and SVG paths, rather than the renderer. They follow the plotter-friendly, geometry-first pattern that the shape booleans set. All of them run off the existing seedable `random`/`noise`, so a run is reproducible. Each ships with an example. Several are the natural implementation behind a [recreation](design-notes.md#examples-folder) of a work by the artist who pioneered them. The conventions for adding one are in the [design notes](design-notes.md#generative-geometry). The broader algorithm catalog is the [technique and algorithm helpers](#technique-and-algorithm-helpers) tier.

- **A crumpled sheet.** A sheet of facets, each a triangle that knows its normal, its center, and how much it faces a light, built from a height function over any region. It is the geometry under crumpled foil, a low-poly ground, or folded paper. A sketch paints each facet with its own fill, hatch, or brush, and a plotter gets the creases as lines. Beside it come the cuts a facet painter needs. A shape splits along a line into its two sides, and a shape clips to a half-plane or to a band between two parallel lines.
- **Textures drawn as lines.** Four textures that are line work, so they plot. Wood grain is streamlines through an angle field whose knots bend the flow and whose rings darken every few lines. Frost is needles sprouted along any outline's normals, barbed and clumped. Crackle is veins that walk across a cell and fork, denser where the surface creases. The fourth is the stepped, bleeding edge of a resist-dyed stripe.

## Technique and algorithm helpers

**Near-term.** This is a standing catalog of classic creative-coding techniques and algorithms as first-class helpers. It keeps growing, as the SDF shapes, the effect `Filter`s, and the [generative-geometry](#generative-geometry) builders do. Each one lands wherever it fits the existing core. A geometry emitter goes beside the shape builders. An escape-time or field technique becomes a GPU `Generator` or shader. A simulation goes beside the compute and `SimField` paths. Each ships with an example, and each runs off the seedable `random`/`noise`, so a result reproduces. Each is implemented from the published technique, which is credited in the Techniques list of `ATTRIBUTION.md`. Many map onto the *Nature of Code* canon (vectors, forces, particles, autonomous agents, cellular automata, fractals, evolution). That makes the catalog a familiar entry point for a reader who comes from that book. The geometry-emitting recipes are flagged plotter-friendly for the pen-plotter path.

- **Soft bodies that rub, meet rigid ones, and fold onto themselves.** A soft body made from an outline slides on the floor and on its neighbors with nothing to slow it, a rigid `Body` passes through it, and a long outline folded back on itself passes through its own side. Friction at every soft contact, contacts between soft and rigid bodies that push both ways, and each outline kept out of itself would close all three.
- **Noise read without the clamp.** `noise` raises its contrast and clamps the overshoot, so a few percent of the field sits flat at 0 and at 1. A form that keeps the whole field, for a curve that should never run flat.
- **Points spread evenly over a sphere.** A list of any number of points on a sphere, each with about the same share of the surface and no clumping at the poles, for a dome of lights, a ball of dots, or directions to aim things along. Sketches write the golden-angle spiral that does this by hand today.
- **Finding boxes and neighbors in 3D.** A bounds index answers which of many boxes contain a point, which overlap a rectangle, and which overlap each other. A 3D form of `SpatialIndex` answers its neighbor questions for point clouds and swarms in space.
- **Matching two sets at the least total cost.** This finds the pairing between two sets of points with the least total distance. Particles can then gather into the letters of a word along the shortest total path, and outlines can pair the same way.
- **Holographic foil.** A filter that renders a layer's shape as crumpled holographic foil. The sheet is facets with their own normals, and the rainbow breaks at every crease because each facet shifts the band by its tilt. Creases are lit or shadowed by how they face the light, and a facet that faces it hardest glints. The layer's own luminance can be the height, so a drawn mark presses into the foil as creases. A stepped ramp, hard stops rather than blends, gives the stripe spectrum, and a light angle and a band phase animate it. An example fills the canvas with a breathing sheet under a drifting light.
- **Chrome for lettering, and interference on a stroke.** The airbrushed chrome of a logo as a filter over a layer's shape. Sky sits above a warped horizon, a dark core band at it, floor below, with a razor break and a bright wire beside it. And the color a thin film shows at a given thickness, on the CPU, so a stroke, a brush, or a polyline can carry a pearl's or a soap film's color from the same spectral model the film filter uses.
- **Material textures.** Surfaces a sketch can ask for by name, as generators and filters over the layer substrate. They are a rust bloom, a verdigris patina, a terrazzo floor, a sheet of bubble wrap that lenses what lies under it, and a crease kernel that folds any heightfield, the paper texture's included.
- **Six optical and print looks.** Each one is a filter. A red-and-cyan anaglyph is driven by a depth map, with the fused dark where the two copies meet. Plate misregistration works on the print separations, each ink shifted and screened at its own angle. A heat mirage shifts each row by a wavering amount, with an inverted copy below a mirror line. Schlieren is the knife-edge shading of a density field. A ramp runs over wavelengths. Chromatography rings are noisy annuli that yield to their neighbors.

See the [design notes](design-notes.md#technique-and-algorithm-helpers).

## Expressive brushes and strokes

This is the hand-drawn, mark-making axis. It is built on the variable-width stroke renderer, which gives a width per vertex, shaped by a `strokeProfile`. It also builds on the recorded marks that drive that renderer from the hand, and on the brushes that stamp a shape along a path. What is ahead is Apple Pencil tilt and azimuth as further drivers. They need a Pencil and a tablet, so they sit under [new input sources](#new-input-sources). Painterly simulation (the generative-watercolor family) stays a [technique-catalog](#technique-and-algorithm-helpers) recipe rather than a brush-engine feature. See the [design notes](design-notes.md#expressive-brushes-and-strokes).

## iPhone as a sensor array

A Mac has no depth camera, no inertial sensors, and no spare Neural Engine for live perception. A tethered iPhone has all three. The idea is to let the phone act as a sensor and an on-device ML co-processor for a sketch that still renders on the Mac. The phone captures and perceives (LiDAR point clouds, face and body tracking, segmentation, device motion, and more). It streams typed results that the sketch reads in `draw()`. A recorded RGBD clip and a tethered phone's live USB RGBD stream already reconstruct on the Mac as point clouds (see [`Docs/3D/Record3D.md`](docs/3d/record3d.md)). That is the kind of world-facing depth feed an Intel RealSense once gave openFrameworks. A sweep of the phone's depth frames fuses by camera pose into one world cloud. That cloud stays registered, and it straightens itself when the phone comes back to a place it has already scanned. Alongside that world cloud, the phone reconstructs the room as a labeled surface (see [`Docs/3D/Phone.md`](docs/3d/phone.md)). The work ahead grows that stream into the rest of the phone's senses, over Ollin's own iPhone capture app. The wire protocol, the sensor catalog, and the build order are in the [design notes](design-notes.md#iphone-as-a-sensor-array).

## 3D mode

2D stays the default, and 3D keeps building out on top of the pieces that already exist. Those are the camera, depth buffer, transform stack, solid primitives, and textured meshes. Meshes loaded from file also belong there, with their materials, textures, and the full surface-map set. The pieces also include the directional/point/spot light and material model, curated lighting presets, and the stylized material library (iridescent, velvet, jade, toon, gooch, …). There is also the physically-based metallic-roughness material, and image-based lighting from bundled, downloaded, or loaded HDRI environments (with a skybox backdrop). The last pieces are matcap materials (view-normal sphere-texture shading) and directional, spot, and point cast shadows. The work ahead builds on all of that:

- **Soft bodies that meet themselves.** Cloth drapes, folds, and holds air. But a folded sheet passes through its own layers, and two sheets pass through each other. That happens because self-collision and cloth-against-cloth are gaps in the solver underneath, not in the API over it. Tearing is further out still. It needs a shared vertex split and a rebuilt constraint set in the middle of a simulation, which that solver cannot do at all. Both wait on the library growing them. When it does, they land as more capability on the shipped `SoftBody3D` surface. A filled jelly held by tetrahedra is *not* on this list. It was built and measured against the `pressure` a closed surface already takes, and the `pressure` form did better. A hair tier is not on the list either. The solver's hair module accepts no force, collides only with convex hulls, and needs an authored groom. The rod family already exposed carries more simulated strands in a frame than that module does. See [`DESIGN-NOTES.md`](design-notes.md).
- **Volumes a GPU kernel writes.** A density grid filled on the GPU by a sketch's own compute kernel, so a smoke simulation or noise 128 samples a side can change every frame and draw as a cloud. Today a grid is filled on the CPU, which keeps a refill every frame to about 32 samples a side.
- **More light in a volume.** A cloud that casts its shadow on the ground under it, the light a thick cloud bounces around inside itself, and fog that veils a volume as it veils a solid.
- **A hologram material.** The rainbow of a diffraction grating by the angle between the light and the eye, the look of a hologram sticker or the back of a compact disc, as the missing sibling of the anodized, nacre, and sequin finishes. Over a crumpled normal map it is holographic foil in 3D.
- **A copy in an instanced draw turned by any rotation.** `MeshInstance` takes its turn as three angles, about x, then y, then z. A turn about any axis is what `rotate(_:)` and the 3D physics bodies speak as a `Rotation3D`, and today it has to be broken into those three angles by hand. That loses precision near a quarter turn about y. A placement that takes a `Rotation3D` directly removes the conversion. [Design notes.](design-notes.md#3d-mode)


3D mode is opt-in, so a 2D sketch never pays for a depth buffer or a perspective divide. The iPhone point cloud renders through it, and visionOS and AR build on it. See the [design notes](design-notes.md#3d-mode).

## Photorealistic 3D

This is the high-end, curated realism tier. It is opt-in on the existing PBR, IBL, ray-traced shadows and reflections, and SDF raymarching. So a 2D or stylized 3D sketch never pays for it. It grows the way the SDF shape catalog does. When a technique that separates a polished product render or film still from "CG" finds a good fit, it lands Metal-native. Each one is written from the published technique and credited in the Techniques list of `ATTRIBUTION.md`. The deeper display levers live under [rendering and color frontier](#rendering-and-color-frontier). There is no queue here, by design. The tier takes the next technique that fits, rather than working through a list.

See the [design notes](design-notes.md#photorealistic-3d).

## Sound, synthesis, and spatial audio

The audio layer both listens and plays. Listening covers FFT, bands, and beat detection. Playing runs through a polyphonic [`Synth`](docs/helpers/synthesis.md) over shaped, filtered voices with delay and reverb. A [composition](docs/helpers/composition.md) tier feeds it and works out what to play. That covers rhythms, keys, chord progressions, tunings past the twelve semitones, and following the beat in the room. The synth is built over waves, wavetables read by position, grains cut out of a sound, and four physical models (two of them driven rather than struck). There is also a patchable operator graph and an ordered chain of effects. The effects are built-in kinds or closures the sketch writes itself. The layer can read [data out as notes](docs/helpers/sonification.md). The sound can be placed in the 3D scene and carried into an exported video.

See the [design notes](design-notes.md#sound-synthesis-and-spatial-audio).

## Live rigs: physical computing, lighting, and network video

The integration tier reaches other software (Syphon, OSC, MIDI, the virtual camera). This tier reaches the hardware and the network around the machine. That is the physical-computing tradition of the frameworks Ollin comes from:

- **NDI.** NDI is the network sibling of Syphon. It sends and receives live video between machines, and it is the standard in VJ and broadcast rigs. It has no published protocol, so unlike the rest of this tier it cannot be written from a specification. It ships as a satellite over the runtime the user installs from NDI: nothing of NDI's in the repository but its MIT-licensed headers, sending first, then receiving. The reasoning against the SDK license is in the design notes.
- **A pen plotter, driven live.** A sketch sends its paths straight to pen plotters such as the AxiDraw over their serial command set. It streams G-code to GRBL-family machines the same way. Pause, pen height, and a preview of what is left to draw come with it. This needs a plotter on the desk to write against.
- **Art-Net discovery.** A console finds its Art-Net nodes by polling the network, and each node answers with its name, its address, and the universes it carries. A sketch that receives Art-Net today has to be given the Mac's address by hand, because Ollin never answers the poll. Answering it puts the sketch in the console's node list, and sending the poll lets `DMXSender` list the nodes on the network instead of taking an address. The reply carries an OEM code that Artistic Licence issues on application, so the application is this item's gate. Helping needs an Art-Net console or node on the network to test against.

All of it follows the interop posture: play in someone's existing rig, do not replace it. See the [design notes](design-notes.md#live-rigs-physical-computing-lighting-and-network-video).

## New input sources

These are more of the platform's live signals. Each one is a `FrameSource` or a simple value read in `draw()`:

- **Apple Pencil.** Tilt, azimuth, and hover on the tablet. The Pencil's force joins the pressure a sketch already reads.
- **Body data, and where the Mac is.** Heart rate from a paired Watch, for biofeedback. The Mac's own location as a slow live input, so a weather can follow the machine.
- **Depth from video, deeper.** The first piece is the metric checkpoint of the video depth model, once its license is settled. With it, a webcam's depth comes in meters and lifts into an `RGBDFrame` and a point cloud. The second piece is the encoder on the Neural Engine, with only the temporal head on the GPU, for twice the readings a second.
- **Pinch and turn on the phone itself.** A sketch installed on a phone or tablet reads a two-finger pinch and turn through the same two values the Mac's trackpad fills.
- **Typed text on the phone itself.** A sketch installed on a phone or tablet reads what its keyboard types through the same `typedText()` the Mac fills.

Several overlap the [iPhone sensor array](#iphone-as-a-sensor-array). These are the Mac-side direct sources. See the [design notes](design-notes.md#new-input-sources).

## New output surfaces

These are ways a sketch leaves the window:

- **Rumble on a game controller.** A game controller's motors are an output of the same kind as [haptics](docs/integration/haptics.md). So they belong with haptics rather than with reading the controller. This needs a controller on the desk to write against.
- **The rest of the sketch on the web page.** The [page export](docs/output/web.md) already carries these parts of a sketch. It carries the analytic shapes, strokes and fills, text and pictures, and the composed and raymarched fields. It also carries the layered effects and the parameters as controls, and it expands strokes and fills on the page from the points the sketch gave. Some things stay with the video export. Those are the effects that are a solve or a ladder on the Mac, lit meshes, ray tracing, and compute work. Pictures that arrive as a texture every frame stay there too. This is not a browser runtime for the framework. That stays out, and the platform stance in `CLAUDE.md` says why.
- **A sketch over the desktop.** The sketch runs in a transparent window that floats above other windows. Clicks pass through wherever the sketch drew nothing, so a piece can stay on screen while you work.
- **A second window.** One sketch draws two views, such as the projector's picture and a control view on the laptop. Two cameras on one world are another case.

See the [design notes](design-notes.md#new-output-surfaces).

## The sketch on a phone, and Swift Playgrounds

A sketch renders through one view on either window system. `Apps/OllinSketchApp` is the reference project for wrapping one as an iOS app. What is ahead is the work around that project: the Swift Playgrounds entry point and the smaller things a device offers.

- **Swift Playgrounds App Projects.** The Swift Playgrounds app has App Projects (`.swiftpm`). They are the closest Swift gets to the p5.js onboarding of "open the editor and type, watch it move". The same package shape embeds a sketch in any SwiftUI app. An App Project is a Swift package, so the [project generator](docs/tools/projectgenerator.md) can write one as a kind of its own. It is the one app-shaped kind that needs no Xcode project and no signing team. One gate stands in front of all of it. The app builds with its own bundled toolchain rather than the Mac's, and the version in the store bundles a Swift a minor below the floor this tree compiles at, so the work waits on a Playgrounds release that catches up, not on anything here. The dependency itself arrives by git URL, which the public repository serves. [Design notes.](design-notes.md#swift-playgrounds-and-ios)
- **The keyboard on a tablet.** A hardware keyboard feeds the same key path a desk sketch reads, through the UIKit press events. So a keyboard-driven sketch is portable too.

See the [design notes](design-notes.md#swift-playgrounds-and-ios).

## Rendering and color frontier

These are deeper uses of the Metal core and Apple displays. All are opt-in, so the 2D path stays untaxed:

- **Dolby Vision.** Dynamic per-scene HDR metadata, in contrast to the static HDR10 metadata a video carries, which describes the whole file at once. It needs the licensed encoder path rather than AVFoundation's plain HDR writer, so it is a licensing question before it is an API one.

See the [design notes](design-notes.md#rendering-and-color-frontier).

## Authoring and editor tooling

**Later.** This section covers the editing experiences the live-reload core makes possible, and where Ollin draws its line on AI: nowhere in the work. The README says it ("It's a tool for making art … Ollin is not a generative-art model"), and it extends to any AI *feature*: **AI helped build the framework, and it plays no part in what you make with it.** Not as the author of a sketch, and not at the controls either, because in generative art the parameters are the work. A palette, a density, a speed chosen by hand is the hand. Models that read the world (the [perception tier](docs/vision/vision.md), depth, listening) are input, like a camera, and stay. The section draws a second line at node editors: the effect and SDF graphs stay code, and a code-less, node-based Ollin would be a separate app on the framework, taken on only if someone wants one. Within those lines:

- **A live window that notices the framework was rebuilt.** A sketch saved after the framework was rebuilt under a running window can crash that window. The window would say to relaunch instead.
- **The rest of a package in the live window.** A sketch that imports another target of its own package, or another package, still runs only through `swift run`. The live window would build those first and load them beside the sketch. The phone route, completion in the live-coding editor, and a shape drag in a helper file each still see the sketch's one file.

See the [design notes](design-notes.md#authoring-and-editor-tooling).

## Collaboration and multi-device

These are Apple-native ways, with little setup, for several machines to share one piece. A **SharePlay** co-creation idea sits under [Further out / exploratory](#further-out-exploratory). Its shape is settled, but it is gated. See the [design notes](design-notes.md#collaboration-and-multi-device).

## Learning: the Guide

**Near-term.** The reference docs ([`Docs/`](docs/index.md)) answer "what does this function do". The [Guide](guide/index.md) is the narrative layer that answers "how do I think in sketches". It is a practical, book-length introduction to creative coding taught through Ollin, written for an engineer with no math, graphics, or Swift background. What is ahead is that the Guide grows in step with the framework. Every capability that ships gets a row in the feature-coverage matrix and a chapter home. The queue, briefs, and coverage plan live in [`Guide/PLAN.md`](https://github.com/eaviles/Ollin/blob/main/Guide/PLAN.md), and the writing rules live in [`Guide/AUTHORING.md`](https://github.com/eaviles/Ollin/blob/main/Guide/AUTHORING.md). The parking lot there reserves a place in the Guide for each item on this page.

## A third-party extension ecosystem

The framework grows past the core team only when other people can publish and find extensions. Other frameworks already have this: p5.js, openFrameworks (`ofx*`), and OPENRNDR (`orx-*`) all have contributed-addon ecosystems. The naming convention, the seams, and the starter are in [Writing an extension](docs/tools/extensions.md). What remains is discovery, and most of it waits on the repository being public:

- **A curated index.** An awesome-list-style page of published extensions, so they can be found without a registry of our own. There is nobody to list yet.
- **Ollin's own front door.** A listing on the Swift Package Index, which is where Swift developers look first, and which builds and hosts the generated API reference for the modules `.spi.yml` names, rebuilding it on every push and keeping a copy per release. A listing is a pull request against the index's own package list, so it is a step somebody takes rather than one that happens. The hand-written [`Docs/`](docs/index.md) stays the curated reference, and the generated one is the API-completeness net under it.
- **A server an assistant can ask, if that is the right call.** An assistant reaches the reference as files: the `llms.txt` map at a checkout's root and the site's, the [quick reference](docs/quickreference.md), and [`ollin api`](docs/tools/reference.md#a-name-and-what-it-takes), all pointing at the same pages. What is open is whether Ollin runs a server of its own over those pages, answering a search rather than handing back a whole page. Most people arriving now work with an assistant. So the reference reaching that assistant accurately is the difference between good sketches and invented API. This is listed as an open question rather than planned work. The reason is that it sits close to a line this project draws deliberately (see the boundary under [authoring and editor tooling](#authoring-and-editor-tooling)). Serving accurate reference so a person can write their own sketch falls on the permitted side. Anything that starts producing sketches does not. Where exactly the line falls here is @eaviles's call, and what waits on it is a server of Ollin's own rather than the reference itself.

See the [design notes](design-notes.md#a-third-party-extension-ecosystem).

## Further out / exploratory

These are lower-confidence ideas, kept on record but deliberately not near-term. Each is plausible on the platform, but it is speculative enough that it should not crowd the planned work above. This section is distinct from [On the horizon](#on-the-horizon), which holds the platform-gated later legs (visionOS, AR), not uncertain ones.

- **SharePlay co-creation.** Two people tune one sketch together over a FaceTime call. The shape is settled. A GroupActivities transport sits behind the room's transport seam and carries the wire it already speaks (parameters, seed, the shared clock). The sketch is bundled as an app and installed on both Macs, because the `com.apple.developer.group-session` entitlement applies to apps only. Tuning is all it covers. An edit to the sketch is a rebuild on both ends, so co-editing code never travels over the call. It waits on three gates, in order. The first is a public repository, because the other person must be able to get the app. The second is a verified real-signing run for the app kind. The third is demand. See the [design notes](design-notes.md#collaboration-and-multi-device).

## On the horizon

These are larger, later directions. 2D on macOS stays the focus, and these do not change that.

- **visionOS.** Immersive rendering uses a different render loop (CompositorServices rather than `MTKView`). So the per-frame loop stays behind a seam that either a normal view or a visionOS layer renderer can drive. It builds on the [3D mode](#3d-mode). [Design notes.](design-notes.md#3d-mode)
- **AR mode and templates.** AR sketches on Apple platforms, with ready-made templates for face, world, and image tracking. With those templates, an AR sketch becomes "fill in the `draw()`, the tracking is handed to you". It is layered on the [phone](#the-sketch-on-a-phone-and-swift-playgrounds) and [3D](#3d-mode) work rather than being a separate engine. It aims at the gap left by discontinued template-driven AR tools. [Design notes.](design-notes.md#ar-mode-and-templates-the-meta-spark-gap)

Neither can be verified at the desk alone. Both need the right SDKs and a device.
