Quickstart
Add Morphic to a Flutter desktop project, initialize the native runner, and run. Three commands and you have a multi-surface app.
flutter pub add morphicdart run morphic:init --applyflutter run -d windowsThen wrap your app with the runtime. Each surface is an ordinary Flutter app behind a named entrypoint the runtime launches:
import 'package:flutter/material.dart';import 'package:morphic/morphic.dart'; // A surface (window) is an ordinary Flutter app behind a named,// tree-shake-safe entrypoint the runtime launches by name.@pragma('vm:entry-point')void mainSurface() => runApp( const MaterialApp( home: Scaffold(body: Center(child: Text('Hello, Morphic'))), ), ); class MyApp extends MorphicApp { @override String get name => 'My App'; @override List<SurfaceSpec> surfaces() => const [ SurfaceSpec.workspace(id: 'main', entrypoint: 'mainSurface'), ];} void main() => MorphicRuntime.run(app: MyApp());Concepts
Morphic introduces a small set of primitives that compose into a full runtime:
- Surface
- A real native window backed by its own Flutter engine.
- Kind
- The role of a surface — workspace, inspector, palette, overlay — which drives native shell behavior.
- Ownership
- Owner chains keep panels raising, minimizing and traveling with their host.
- Group / Dock
- Surfaces that converge form a group; rigid co-movement follows.
- Extraction
- A grouped surface can detach mid-interaction into its own session.
- Orchestration
- A deterministic semantic runtime governs z-order and activation.
SDK
The authoring surface is intentionally small. You declare what surfaces exist; each is its own engine behind a named entrypoint. Add a window with one more spec:
@pragma('vm:entry-point')void inspector() => runApp( const MaterialApp( home: Scaffold(body: Center(child: Text('Inspector'))), ), ); // Each surface is its own engine. Declare it alongside the workspace:@overrideList<SurfaceSpec> surfaces() => const [ SurfaceSpec.workspace(id: 'main', entrypoint: 'mainSurface'), SurfaceSpec.inspector(id: 'inspector', entrypoint: 'inspector'), ];Surfaces never reach into each other. They communicate through a shared app bus, staying in sync while remaining isolated, independently-rendered windows:
// Surfaces never reach into each other — they broadcast and react.AppBus.broadcast('note.selected', {'id': id});AppBus.on('note.selected', (p) => open(p['id'] as String)); // A surface only acts on itself:MorphicSurface.minimize();MorphicSurface.close();Integration
Morphic wraps your existing Flutter app — it doesn't replace it. Add the dependency, run the initializer, and adopt surfaces incrementally.
dependencies: morphic: ^0.4.0-beta.3dart run morphic:init --apply wires the native multi-surface runner into your windows/ directory. Your widget tree is untouched.
Runtime Modes
Real OS windows with native shell semantics — taskbar, Alt-Tab, owner chains, deterministic z-order. Available today.
GPU-composited surfaces on a shared plane with materials, blur and scene zoom. Available for experimentation.
Spatial surfaces
Spatial surfaces are the same SurfaceSpec you already use — you just set its spatial fields. They render only on the Spatial runtime (sign in below); on the free native runtime they no-op and the surface degrades to an ordinary window.
// A glass panel with a composed capsule header (Spatial runtime).// Every fixed-value option is a typed enum — a typo is a compile error.List<SurfaceSpec> surfaces() => const [ SurfaceSpec.workspace( id: 'panel', entrypoint: 'panelMain', width: 1040, height: 620, backend: SurfaceBackend.spatial, // GPU-composited shaped visual material: SurfaceMaterial.acrylic, // real compositor blur materialTint: 0x59FFFFFF, // ARGB tint over the blur cornerRadius: 28, elevation: 26, // compositor shadow depth (px) chromeless: true, transparency: SurfaceTransparency.fullGlass, ), SurfaceSpec.inspector( id: 'header', entrypoint: 'headerMain', parent: 'panel', composed: true, // joins the panel's composition plane backend: SurfaceBackend.spatial, shape: SurfaceShape.capsule, // rounded | capsule | hexagon | circle material: SurfaceMaterial.acrylic, materialTint: 0x59FFFFFF, elevation: 18, chromeless: true, transparency: SurfaceTransparency.fullGlass, ),];SurfaceBackend native | spatial · SurfaceShape rounded | capsule | hexagon | circle · SurfaceMaterial none | acrylic · materialTint ARGB · elevation px shadow · composed join the parent's composition plane. The native appearance fields (chromeless, SurfaceTransparency, SurfaceBackdrop, SurfaceCorners) work on the free tier too.
Sign in & Spatial
Native mode needs no account — add the package and you're building. An account is only for the optional Spatial runtime, which is a free Developer Preview (no payment, no pricing).
Sign in from the CLI — it opens your browser, you sign in with Google, and a token is stored locally. There is no license key to paste.
dart run morphic:login # opens your browser, sign in with Googledart run morphic:license # shows your tier + spatial accessThen enable the Spatial runtime:
dart run morphic:login # sign in (once)dart run morphic:init --spatial --apply # secure delivery + installExperimental. The CLI talks to www.getmorphic.space by default (override with the MORPHIC_API_URL env var). Manage your access anytime on the dashboard.
Architecture
The runtime is layered as a series of clean, swappable boundaries — each stage transforms intent into pixels on screen:
The source of truth: what surfaces exist and how they relate.
Drag, dock, group and extract gestures resolved deterministically.
Smoothing and coherence between semantic truth and native windows.
Geometry and z-order projected onto real OS windows.
The platform shell — Win32 today, more to come.