diff --git a/README.md b/README.md
index 56b4a5658081517fc00215f598ab4d98e9578421..0bdff19ce9f64b9db67697e745058ce02ba744bf 100644
--- a/README.md
+++ b/README.md
@@ -17,12 +17,14 @@ The core of Mol* currently consists of these modules:
 - `mol-math` Math related (loosely) algorithms and data structures.
 - `mol-io` Parsing library. Each format is parsed into an interface that corresponds to the data stored by it. Support for common coordinate, experimental/map, and annotation data formats.
 - `mol-model` Data structures and algorithms (such as querying) for representing molecular data (including coordinate, experimental/map, and annotation data).
-- `mol-model-props` Common "custom properties"
+- `mol-model-props` Common "custom properties".
 - `mol-script` A scriting language for creating representations/scenes and querying (includes the [MolQL query language](https://molql.github.io)).
 - `mol-geo` Creating molecular geometries.
-- `mol-gl` A wrapper around WebGL. Uses `mol-geo` to generate geometries.
+- `mol-gl` A lightweight wrapper around WebGL.
+- `mol-canvas3d` A low level 3d view component. Uses `mol-geo` to generate geometries.
+- `mol-state` State representation tree with state saving and automatic updates.
 - `mol-app` Components for builduing UIs.
-- `mol-view` A reference viewer implementation.
+- `mol-plugin` Allow to define modular Mol* plugin instances utilizing `mol-state` and `mol-view3d`.
 - `mol-util` Useful things that do not fit elsewhere.
 
 Moreover, the project contains the imlementation of `servers`, including
diff --git a/package.json b/package.json
index 6a807c3a05c31a48daca707f8772ca405522c130..9cb1cdafb711b5162f7d739d0360eeb6b0a6e746 100644
--- a/package.json
+++ b/package.json
@@ -61,8 +61,9 @@
       "mol-script($|/.*)": "<rootDir>/src/mol-script$1",
       "mol-task($|/.*)": "<rootDir>/src/mol-task$1",
       "mol-state($|/.*)": "<rootDir>/src/mol-state$1",
+      "mol-plugin($|/.*)": "<rootDir>/src/mol-plugin$1",
       "mol-util($|/.*)": "<rootDir>/src/mol-util$1",
-      "mol-view($|/.*)": "<rootDir>/src/mol-view$1"
+      "mol-canvas3d($|/.*)": "<rootDir>/src/mol-canvas3d$1"
     },
     "testRegex": "\\.spec\\.ts$"
   },
diff --git a/src/apps/canvas/app.ts b/src/apps/canvas/app.ts
index f72add32be2129c55e97d5824848a92a4dd1b251..0abfc41d430aa854d947292d8094b0b44496719a 100644
--- a/src/apps/canvas/app.ts
+++ b/src/apps/canvas/app.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import Viewer from 'mol-view/viewer';
+import Viewer from 'mol-canvas3d/viewer';
 import { getCifFromUrl, getModelsFromMmcif, getCifFromFile, getCcp4FromUrl, getVolumeFromCcp4, getCcp4FromFile, getVolumeFromVolcif } from './util';
 import { StructureView } from './structure-view';
 import { BehaviorSubject } from 'rxjs';
diff --git a/src/apps/canvas/assembly-symmetry.ts b/src/apps/canvas/assembly-symmetry.ts
index ee4d6832753ef4a2f379f5004ede22078ff26eab..6929fb091e396abe07432ebf6a029f92a4766b6b 100644
--- a/src/apps/canvas/assembly-symmetry.ts
+++ b/src/apps/canvas/assembly-symmetry.ts
@@ -12,7 +12,7 @@ import { Tensor } from 'mol-math/linear-algebra';
 import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere';
 import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder';
 import { Shape } from 'mol-model/shape';
-import { ColorTheme } from 'mol-view/theme/color';
+import { ColorTheme } from 'mol-canvas3d/theme/color';
 import { Location } from 'mol-model/location';
 import { StructureElement, Unit, StructureProperties } from 'mol-model/structure';
 
diff --git a/src/apps/canvas/component/representation.tsx b/src/apps/canvas/component/representation.tsx
index 56928666fac6d30eabe66a6deef145d52e8eb92a..c5284562edf4128239df3441b2cb6f9ee76abd61 100644
--- a/src/apps/canvas/component/representation.tsx
+++ b/src/apps/canvas/component/representation.tsx
@@ -5,13 +5,13 @@
  */
 
 import * as React from 'react'
-import Viewer from 'mol-view/viewer';
+import Viewer from 'mol-canvas3d/viewer';
 import { App } from '../app';
-import { Params } from 'mol-view/parameter';
+import { Params } from 'mol-util/parameter';
 import { Representation } from 'mol-geo/representation';
 import { ParametersComponent } from 'mol-app/component/parameters';
 import { Progress } from 'mol-task';
-import { ColorTheme } from 'mol-view/theme/color';
+import { ColorTheme } from 'mol-canvas3d/theme/color';
 import { getColorThemeProps } from 'mol-geo/geometry/color-data';
 import { ColorThemeComponent } from 'mol-app/component/color-theme';
 
diff --git a/src/apps/canvas/component/viewport.tsx b/src/apps/canvas/component/viewport.tsx
index 0085461d7f307e8d3d9849eff9cfa645af1a23bd..7814b26479102e741894b4662e75bc8134029770 100644
--- a/src/apps/canvas/component/viewport.tsx
+++ b/src/apps/canvas/component/viewport.tsx
@@ -8,7 +8,7 @@ import * as React from 'react'
 import { App } from '../app';
 import { MarkerAction } from 'mol-geo/geometry/marker-data';
 import { EmptyLoci, Loci, areLociEqual } from 'mol-model/loci';
-import { labelFirst } from 'mol-view/label';
+import { labelFirst } from 'mol-canvas3d/label';
 
 interface ViewportProps {
     app: App
diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts
index 768dfb01ba9c2d5e16c0f4f4f8f7efb5a7b10623..f78d02f9786b74d03f632b02eafe5de50a6902ed 100644
--- a/src/apps/canvas/structure-view.ts
+++ b/src/apps/canvas/structure-view.ts
@@ -11,7 +11,7 @@ import { getStructureFromModel } from './util';
 import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry';
 import { ShapeRepresentation, ShapeProps } from 'mol-geo/representation/shape';
 import { getAxesShape } from './assembly-symmetry';
-import Viewer from 'mol-view/viewer';
+import Viewer from 'mol-canvas3d/viewer';
 import { CarbohydrateRepresentation } from 'mol-geo/representation/structure/representation/carbohydrate';
 // import { MeshBuilder } from 'mol-geo/mesh/mesh-builder';
 // import { addSphere } from 'mol-geo/mesh/builder/sphere';
diff --git a/src/apps/canvas/volume-view.ts b/src/apps/canvas/volume-view.ts
index 1ef40f6dda5e97284b971906a8fa556215f64976..a680383918049f3d54e6dbed6982721a11a8be44 100644
--- a/src/apps/canvas/volume-view.ts
+++ b/src/apps/canvas/volume-view.ts
@@ -4,7 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import Viewer from 'mol-view/viewer';
+import Viewer from 'mol-canvas3d/viewer';
 import { BehaviorSubject } from 'rxjs';
 import { App } from './app';
 import { Progress } from 'mol-task';
diff --git a/src/mol-app/component/color-theme.tsx b/src/mol-app/component/color-theme.tsx
index 4b4c78311c2c44fdf1d48a67374edf27aa5671d0..3c8b414de5c60b83ef00d86e36ebbb552d35f823 100644
--- a/src/mol-app/component/color-theme.tsx
+++ b/src/mol-app/component/color-theme.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { ColorTheme } from 'mol-view/theme/color';
+import { ColorTheme } from 'mol-canvas3d/theme/color';
 import { Color } from 'mol-util/color';
 
 export interface ColorThemeComponentProps {
diff --git a/src/mol-app/component/parameter/boolean.tsx b/src/mol-app/component/parameter/boolean.tsx
index 997b2ca5c42da85f838cd07bda3e2d1edb6d019a..5862efc1dda36de60f1cd45ee5c315b1f75de2d3 100644
--- a/src/mol-app/component/parameter/boolean.tsx
+++ b/src/mol-app/component/parameter/boolean.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { BooleanParam } from 'mol-view/parameter';
+import { BooleanParam } from 'mol-util/parameter';
 
 export interface BooleanParamComponentProps {
     param: BooleanParam
diff --git a/src/mol-app/component/parameter/multi-select.tsx b/src/mol-app/component/parameter/multi-select.tsx
index d23e31feebdb027d975acf840782108e75ea88eb..79e66af6b6211039f480272e5abe61fb4002ac55 100644
--- a/src/mol-app/component/parameter/multi-select.tsx
+++ b/src/mol-app/component/parameter/multi-select.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { MultiSelectParam } from 'mol-view/parameter';
+import { MultiSelectParam } from 'mol-util/parameter';
 
 export interface MultiSelectParamComponentProps<T extends string> {
     param: MultiSelectParam<T>
diff --git a/src/mol-app/component/parameter/number.tsx b/src/mol-app/component/parameter/number.tsx
index be97aee26f79de663689de062c0fecdc912e9291..c693b7d910810c72049f0fb01cce153d4ae1b9eb 100644
--- a/src/mol-app/component/parameter/number.tsx
+++ b/src/mol-app/component/parameter/number.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { NumberParam } from 'mol-view/parameter';
+import { NumberParam } from 'mol-util/parameter';
 
 export interface NumberParamComponentProps {
     param: NumberParam
diff --git a/src/mol-app/component/parameter/range.tsx b/src/mol-app/component/parameter/range.tsx
index dd9c82fa236d6d6d62a7092c50fccb8d4c725dad..42d5450a1febd49c651ea6f4c2865545305ca1bb 100644
--- a/src/mol-app/component/parameter/range.tsx
+++ b/src/mol-app/component/parameter/range.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { RangeParam } from 'mol-view/parameter';
+import { RangeParam } from 'mol-util/parameter';
 
 export interface RangeParamComponentProps {
     param: RangeParam
diff --git a/src/mol-app/component/parameter/select.tsx b/src/mol-app/component/parameter/select.tsx
index e403bbb79f2cd56c9dbf5e878e7f41229d317012..c0034953fc3c77f059918702f510b88e2a37b300 100644
--- a/src/mol-app/component/parameter/select.tsx
+++ b/src/mol-app/component/parameter/select.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { SelectParam } from 'mol-view/parameter';
+import { SelectParam } from 'mol-util/parameter';
 
 export interface SelectParamComponentProps<T extends string> {
     param: SelectParam<T>
diff --git a/src/mol-app/component/parameter/text.tsx b/src/mol-app/component/parameter/text.tsx
index cd6ad76f78ecfab597df5bc17ae99f5ace5c3742..507754f5fef8e35020e19de676b0c88afaeb5283 100644
--- a/src/mol-app/component/parameter/text.tsx
+++ b/src/mol-app/component/parameter/text.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { TextParam } from 'mol-view/parameter';
+import { TextParam } from 'mol-util/parameter';
 
 export interface TextParamComponentProps {
     param: TextParam
diff --git a/src/mol-app/component/parameters.tsx b/src/mol-app/component/parameters.tsx
index 70e2aee371658e3c1696908ffd50e419b948c6a8..0fc247b25b19a35349474e31d430b201862ae31d 100644
--- a/src/mol-app/component/parameters.tsx
+++ b/src/mol-app/component/parameters.tsx
@@ -5,7 +5,7 @@
  */
 
 import * as React from 'react'
-import { Param, Params } from 'mol-view/parameter';
+import { Param, Params } from 'mol-util/parameter';
 import { BooleanParamComponent } from './parameter/boolean';
 import { NumberParamComponent } from './parameter/number';
 import { RangeParamComponent } from './parameter/range';
diff --git a/src/mol-view/camera/base.ts b/src/mol-canvas3d/camera/base.ts
similarity index 100%
rename from src/mol-view/camera/base.ts
rename to src/mol-canvas3d/camera/base.ts
diff --git a/src/mol-view/camera/orthographic.ts b/src/mol-canvas3d/camera/orthographic.ts
similarity index 100%
rename from src/mol-view/camera/orthographic.ts
rename to src/mol-canvas3d/camera/orthographic.ts
diff --git a/src/mol-view/camera/perspective.ts b/src/mol-canvas3d/camera/perspective.ts
similarity index 100%
rename from src/mol-view/camera/perspective.ts
rename to src/mol-canvas3d/camera/perspective.ts
diff --git a/src/mol-view/camera/util.ts b/src/mol-canvas3d/camera/util.ts
similarity index 100%
rename from src/mol-view/camera/util.ts
rename to src/mol-canvas3d/camera/util.ts
diff --git a/src/mol-view/controls/trackball.ts b/src/mol-canvas3d/controls/trackball.ts
similarity index 100%
rename from src/mol-view/controls/trackball.ts
rename to src/mol-canvas3d/controls/trackball.ts
diff --git a/src/mol-view/label.ts b/src/mol-canvas3d/label.ts
similarity index 100%
rename from src/mol-view/label.ts
rename to src/mol-canvas3d/label.ts
diff --git a/src/mol-view/theme/color.ts b/src/mol-canvas3d/theme/color.ts
similarity index 100%
rename from src/mol-view/theme/color.ts
rename to src/mol-canvas3d/theme/color.ts
diff --git a/src/mol-view/theme/color/carbohydrate-symbol.ts b/src/mol-canvas3d/theme/color/carbohydrate-symbol.ts
similarity index 100%
rename from src/mol-view/theme/color/carbohydrate-symbol.ts
rename to src/mol-canvas3d/theme/color/carbohydrate-symbol.ts
diff --git a/src/mol-view/theme/color/chain-id.ts b/src/mol-canvas3d/theme/color/chain-id.ts
similarity index 100%
rename from src/mol-view/theme/color/chain-id.ts
rename to src/mol-canvas3d/theme/color/chain-id.ts
diff --git a/src/mol-view/theme/color/cross-link.ts b/src/mol-canvas3d/theme/color/cross-link.ts
similarity index 100%
rename from src/mol-view/theme/color/cross-link.ts
rename to src/mol-canvas3d/theme/color/cross-link.ts
diff --git a/src/mol-view/theme/color/custom.ts b/src/mol-canvas3d/theme/color/custom.ts
similarity index 100%
rename from src/mol-view/theme/color/custom.ts
rename to src/mol-canvas3d/theme/color/custom.ts
diff --git a/src/mol-view/theme/color/element-index.ts b/src/mol-canvas3d/theme/color/element-index.ts
similarity index 100%
rename from src/mol-view/theme/color/element-index.ts
rename to src/mol-canvas3d/theme/color/element-index.ts
diff --git a/src/mol-view/theme/color/element-symbol.ts b/src/mol-canvas3d/theme/color/element-symbol.ts
similarity index 100%
rename from src/mol-view/theme/color/element-symbol.ts
rename to src/mol-canvas3d/theme/color/element-symbol.ts
diff --git a/src/mol-view/theme/color/molecule-type.ts b/src/mol-canvas3d/theme/color/molecule-type.ts
similarity index 100%
rename from src/mol-view/theme/color/molecule-type.ts
rename to src/mol-canvas3d/theme/color/molecule-type.ts
diff --git a/src/mol-view/theme/color/residue-name.ts b/src/mol-canvas3d/theme/color/residue-name.ts
similarity index 100%
rename from src/mol-view/theme/color/residue-name.ts
rename to src/mol-canvas3d/theme/color/residue-name.ts
diff --git a/src/mol-view/theme/color/secondary-structure.ts b/src/mol-canvas3d/theme/color/secondary-structure.ts
similarity index 100%
rename from src/mol-view/theme/color/secondary-structure.ts
rename to src/mol-canvas3d/theme/color/secondary-structure.ts
diff --git a/src/mol-view/theme/color/sequence-id.ts b/src/mol-canvas3d/theme/color/sequence-id.ts
similarity index 100%
rename from src/mol-view/theme/color/sequence-id.ts
rename to src/mol-canvas3d/theme/color/sequence-id.ts
diff --git a/src/mol-view/theme/color/shape-group.ts b/src/mol-canvas3d/theme/color/shape-group.ts
similarity index 100%
rename from src/mol-view/theme/color/shape-group.ts
rename to src/mol-canvas3d/theme/color/shape-group.ts
diff --git a/src/mol-view/theme/color/uniform.ts b/src/mol-canvas3d/theme/color/uniform.ts
similarity index 100%
rename from src/mol-view/theme/color/uniform.ts
rename to src/mol-canvas3d/theme/color/uniform.ts
diff --git a/src/mol-view/theme/color/unit-index.ts b/src/mol-canvas3d/theme/color/unit-index.ts
similarity index 100%
rename from src/mol-view/theme/color/unit-index.ts
rename to src/mol-canvas3d/theme/color/unit-index.ts
diff --git a/src/mol-view/theme/size.ts b/src/mol-canvas3d/theme/size.ts
similarity index 100%
rename from src/mol-view/theme/size.ts
rename to src/mol-canvas3d/theme/size.ts
diff --git a/src/mol-view/theme/size/physical.ts b/src/mol-canvas3d/theme/size/physical.ts
similarity index 100%
rename from src/mol-view/theme/size/physical.ts
rename to src/mol-canvas3d/theme/size/physical.ts
diff --git a/src/mol-view/theme/size/uniform.ts b/src/mol-canvas3d/theme/size/uniform.ts
similarity index 100%
rename from src/mol-view/theme/size/uniform.ts
rename to src/mol-canvas3d/theme/size/uniform.ts
diff --git a/src/mol-canvas3d/util.ts b/src/mol-canvas3d/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..294907ad30cdd987b883f7b95848829de48a611e
--- /dev/null
+++ b/src/mol-canvas3d/util.ts
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+export function resizeCanvas (canvas: HTMLCanvasElement, container: Element) {
+    let w = window.innerWidth
+    let h = window.innerHeight
+    if (container !== document.body) {
+        let bounds = container.getBoundingClientRect()
+        w = bounds.right - bounds.left
+        h = bounds.bottom - bounds.top
+    }
+    canvas.width = window.devicePixelRatio * w
+    canvas.height = window.devicePixelRatio * h
+    Object.assign(canvas.style, { width: `${w}px`, height: `${h}px` })
+}
\ No newline at end of file
diff --git a/src/mol-view/viewer.ts b/src/mol-canvas3d/viewer.ts
similarity index 100%
rename from src/mol-view/viewer.ts
rename to src/mol-canvas3d/viewer.ts
diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts
index b02d20440eaadab735f53fba0ec472a612586140..fe1dfae7bc2f5e7bca39848decafe37e3cceca47 100644
--- a/src/mol-geo/geometry/color-data.ts
+++ b/src/mol-geo/geometry/color-data.ts
@@ -10,7 +10,7 @@ import { Color } from 'mol-util/color';
 import { Vec2, Vec3 } from 'mol-math/linear-algebra';
 import { LocationIterator } from '../util/location-iterator';
 import { NullLocation } from 'mol-model/location';
-import { LocationColor, ColorThemeProps, ColorTheme, ColorThemeName } from 'mol-view/theme/color';
+import { LocationColor, ColorThemeProps, ColorTheme, ColorThemeName } from 'mol-canvas3d/theme/color';
 import { RuntimeContext } from 'mol-task';
 import { getGranularity } from './geometry';
 import { Structure } from 'mol-model/structure';
diff --git a/src/mol-geo/geometry/direct-volume/direct-volume.ts b/src/mol-geo/geometry/direct-volume/direct-volume.ts
index 76458adaa367d96f27246924f0b2fa11821fe7a3..d0057084b5b420b0f566401997c5720349bfe551 100644
--- a/src/mol-geo/geometry/direct-volume/direct-volume.ts
+++ b/src/mol-geo/geometry/direct-volume/direct-volume.ts
@@ -7,7 +7,7 @@
 import { RuntimeContext } from 'mol-task'
 import { ValueCell } from 'mol-util'
 import { Sphere3D, Box3D } from 'mol-math/geometry'
-import { paramDefaultValues, RangeParam, SelectParam, TextParam } from 'mol-view/parameter';
+import { paramDefaultValues, RangeParam, SelectParam, TextParam } from 'mol-util/parameter';
 import { DirectVolumeValues } from 'mol-gl/renderable/direct-volume';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Box } from '../../primitive/box';
diff --git a/src/mol-geo/geometry/direct-volume/transfer-function.ts b/src/mol-geo/geometry/direct-volume/transfer-function.ts
index 9c6cd1424b4bcb5b38d9b4a7730e5da8d375a5bf..98f496f143517cebdb1345d5a7a48168ecb9b94b 100644
--- a/src/mol-geo/geometry/direct-volume/transfer-function.ts
+++ b/src/mol-geo/geometry/direct-volume/transfer-function.ts
@@ -18,7 +18,7 @@ export function getControlPointsFromString(s: string): ControlPoint[] {
         return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) }
     })
 }
-// TODO move core function to mol-view/color
+// TODO move core function to mol-canvas3d/color
 export function createTransferFunctionTexture(controlPoints: ControlPoint[], texture?: ValueCell<TextureImage<Uint8Array>>): ValueCell<TextureImage<Uint8Array>> {
     const cp = [
         { x: 0, alpha: 0 },
diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts
index d9e7e2f0d212972df39a0fc4638fa956a40b58e3..dcabc03539082956e2afdb4ee9bb843d60b63511 100644
--- a/src/mol-geo/geometry/geometry.ts
+++ b/src/mol-geo/geometry/geometry.ts
@@ -10,13 +10,12 @@ import { RenderableState } from 'mol-gl/renderable';
 import { ValueCell } from 'mol-util';
 import { BaseValues } from 'mol-gl/renderable/schema';
 import { Color } from 'mol-util/color';
-import { ColorThemeOptions, ColorThemeName } from 'mol-view/theme/color';
+import { ColorThemeOptions, ColorThemeName } from 'mol-canvas3d/theme/color';
 import { LocationIterator } from '../util/location-iterator';
 import { ColorType } from './color-data';
 import { SizeType } from './size-data';
 import { Lines } from './lines/lines';
-import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, StructureParam, ValueParam } from 'mol-view/parameter'
-import { Structure } from 'mol-model/structure';
+import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, ValueParam } from 'mol-util/parameter'
 import { DirectVolume } from './direct-volume/direct-volume';
 import { Context } from 'mol-gl/webgl/context';
 
@@ -68,7 +67,6 @@ export namespace Geometry {
         quality: SelectParam<VisualQuality>('Quality', '', 'auto', VisualQualityOptions),
         colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'uniform', ColorThemeOptions),
         colorValue: ColorParam('Color Value', '', Color(0xCCCCCC)),
-        structure: StructureParam('Structure', '', Structure.Empty),
         webgl: ValueParam('WebGL Context', '', undefined as Context | undefined),
     }
     export const DefaultProps = paramDefaultValues(Params)
diff --git a/src/mol-geo/geometry/lines/lines.ts b/src/mol-geo/geometry/lines/lines.ts
index 84b565d1d1df3460e108c8a64303d190dfc4a384..c4e80b3f3ce696a1f963c1089961b02c55414209 100644
--- a/src/mol-geo/geometry/lines/lines.ts
+++ b/src/mol-geo/geometry/lines/lines.ts
@@ -14,11 +14,11 @@ import { createMarkers } from '../marker-data';
 import { createSizes } from '../size-data';
 import { TransformData } from '../transform-data';
 import { LocationIterator } from '../../util/location-iterator';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { LinesValues } from 'mol-gl/renderable/lines';
 import { Mesh } from '../mesh/mesh';
 import { LinesBuilder } from './lines-builder';
-import { BooleanParam, SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { BooleanParam, SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 /** Wide line */
 export interface Lines {
diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts
index ad4cec0ba85172c3fb8b961543413b8248132f2b..14a204f9c3039dea431a09522aa3ebf47efe80cc 100644
--- a/src/mol-geo/geometry/mesh/mesh.ts
+++ b/src/mol-geo/geometry/mesh/mesh.ts
@@ -16,7 +16,7 @@ import { TransformData } from '../transform-data';
 import { LocationIterator } from '../../util/location-iterator';
 import { createColors } from '../color-data';
 import { ChunkedArray } from 'mol-data/util';
-import { BooleanParam, paramDefaultValues } from 'mol-view/parameter';
+import { BooleanParam, paramDefaultValues } from 'mol-util/parameter';
 
 export interface Mesh {
     readonly kind: 'mesh',
diff --git a/src/mol-geo/geometry/points/points.ts b/src/mol-geo/geometry/points/points.ts
index 3181353cf9957302fccf4cc00f2bef5a4910065d..3a4799600ee35d75cfeed51fb2c5fb4dca7635b3 100644
--- a/src/mol-geo/geometry/points/points.ts
+++ b/src/mol-geo/geometry/points/points.ts
@@ -15,8 +15,8 @@ import { createMarkers } from '../marker-data';
 import { createSizes } from '../size-data';
 import { TransformData } from '../transform-data';
 import { LocationIterator } from '../../util/location-iterator';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
-import { BooleanParam, NumberParam, SelectParam, paramDefaultValues } from 'mol-view/parameter';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
+import { BooleanParam, NumberParam, SelectParam, paramDefaultValues } from 'mol-util/parameter';
 
 /** Point cloud */
 export interface Points {
diff --git a/src/mol-geo/geometry/size-data.ts b/src/mol-geo/geometry/size-data.ts
index 81373ef582083d81fd42ea6af46c31de3e1294db..8a5d574b3a69cd77cee0b9c74d7cb380a100ab20 100644
--- a/src/mol-geo/geometry/size-data.ts
+++ b/src/mol-geo/geometry/size-data.ts
@@ -10,7 +10,7 @@ import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
 import { LocationIterator } from '../util/location-iterator';
 import { Location, NullLocation } from 'mol-model/location';
 import { RuntimeContext } from 'mol-task';
-import { SizeThemeProps, SizeTheme, SizeThemeName } from 'mol-view/theme/size';
+import { SizeThemeProps, SizeTheme, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { getGranularity } from './geometry';
 import { Structure } from 'mol-model/structure';
 
diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts
index 0a35e6e892286800372ad3098f52a9612d836cac..e9ca9e4c26f503cf30a186fa3e4fbf96394c1ce7 100644
--- a/src/mol-geo/representation/index.ts
+++ b/src/mol-geo/representation/index.ts
@@ -9,7 +9,7 @@ import { RenderObject } from 'mol-gl/render-object'
 import { PickingId } from '../geometry/picking';
 import { Loci } from 'mol-model/loci';
 import { MarkerAction } from '../geometry/marker-data';
-import { Params } from 'mol-view/parameter';
+import { Params } from 'mol-util/parameter';
 
 export interface RepresentationProps {}
 
diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-geo/representation/shape/index.ts
index 6c1f7b1ff79a897a43c5f097b2533712470b5e7a..43b4d06f6d8fff6055fd1f96db25fbfbbdc819ad 100644
--- a/src/mol-geo/representation/shape/index.ts
+++ b/src/mol-geo/representation/shape/index.ts
@@ -11,14 +11,14 @@ import { PickingId } from '../../geometry/picking';
 import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci';
 import { MarkerAction, applyMarkerAction } from '../../geometry/marker-data';
 import { ValueCell } from 'mol-util';
-import { ColorThemeName, ColorThemeOptions } from 'mol-view/theme/color';
+import { ColorThemeName, ColorThemeOptions } from 'mol-canvas3d/theme/color';
 import { Shape } from 'mol-model/shape';
 import { LocationIterator } from '../../util/location-iterator';
 import { OrderedSet, Interval } from 'mol-data/int';
 import { createIdentityTransform } from '../../geometry/transform-data';
 import { createRenderableState } from '../../geometry/geometry';
 import { Mesh } from '../../geometry/mesh/mesh';
-import { paramDefaultValues, SelectParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam } from 'mol-util/parameter';
 
 export interface ShapeRepresentation<P extends RepresentationProps = {}> extends Representation<Shape, P> { }
 
diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-geo/representation/structure/complex-visual.ts
index 02bfb79588f31013725f319de8d95486d6e7b5b9..aac01779c41a402b9e710bda94e7d9390152a064 100644
--- a/src/mol-geo/representation/structure/complex-visual.ts
+++ b/src/mol-geo/representation/structure/complex-visual.ts
@@ -19,7 +19,7 @@ import { MarkerAction, applyMarkerAction } from '../../geometry/marker-data';
 import { Interval } from 'mol-data/int';
 import { updateRenderableState, Geometry } from '../../geometry/geometry';
 import { createColors } from '../../geometry/color-data';
-import { MultiSelectParam, paramDefaultValues } from 'mol-view/parameter';
+import { MultiSelectParam, paramDefaultValues } from 'mol-util/parameter';
 import { RenderableValues } from 'mol-gl/renderable/schema';
 import { createSizes } from 'mol-geo/geometry/size-data';
 
diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts
index b5c094fc2efb84ec161a72296e1d7015d7076a16..01769aeabde78beeaab85f795a52abfa30f1491a 100644
--- a/src/mol-geo/representation/structure/index.ts
+++ b/src/mol-geo/representation/structure/index.ts
@@ -6,14 +6,14 @@
  */
 
 import { Structure } from 'mol-model/structure';
-import { ColorThemeName, ColorThemeOptions } from 'mol-view/theme/color';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { ColorThemeName, ColorThemeOptions } from 'mol-canvas3d/theme/color';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { Representation, RepresentationProps } from '..';
 import { Geometry } from '../../geometry/geometry';
 import { Mesh } from '../../geometry/mesh/mesh';
 import { Points } from '../../geometry/points/points';
 import { Lines } from '../../geometry/lines/lines';
-import { SelectParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, paramDefaultValues } from 'mol-util/parameter';
 import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 
 export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
diff --git a/src/mol-geo/representation/structure/representation/backbone.ts b/src/mol-geo/representation/structure/representation/backbone.ts
index ad6e7e641d94be2794c4b22793a06c5bf0499d49..ecfa4da0454e3e770b62462e23dd27fdf36724fb 100644
--- a/src/mol-geo/representation/structure/representation/backbone.ts
+++ b/src/mol-geo/representation/structure/representation/backbone.ts
@@ -12,7 +12,7 @@ import { Loci } from 'mol-model/loci';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { PolymerBackboneVisual, PolymerBackboneParams } from '../visual/polymer-backbone-cylinder';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 export const BackboneParams = {
     ...PolymerBackboneParams
diff --git a/src/mol-geo/representation/structure/representation/ball-and-stick.ts b/src/mol-geo/representation/structure/representation/ball-and-stick.ts
index 90eec78fea53099686fdd74a0d436b890df4ea6e..c4f50b145a948c1c9b69625afe8b9d52f922964a 100644
--- a/src/mol-geo/representation/structure/representation/ball-and-stick.ts
+++ b/src/mol-geo/representation/structure/representation/ball-and-stick.ts
@@ -13,9 +13,9 @@ import { Task } from 'mol-task';
 import { Loci, isEmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { InterUnitLinkVisual } from '../visual/inter-unit-link-cylinder';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam, MultiSelectParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam, NumberParam, MultiSelectParam } from 'mol-util/parameter';
 import { UnitKind, UnitKindOptions } from '../visual/util/common';
 
 export const BallAndStickParams = {
diff --git a/src/mol-geo/representation/structure/representation/carbohydrate.ts b/src/mol-geo/representation/structure/representation/carbohydrate.ts
index 89b348ba7ebfa92bd170b9985c985da9c7bb405e..17373bbcebbcedb38a4b6a0325bd23eb9111e759 100644
--- a/src/mol-geo/representation/structure/representation/carbohydrate.ts
+++ b/src/mol-geo/representation/structure/representation/carbohydrate.ts
@@ -12,9 +12,9 @@ import { Loci, isEmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { CarbohydrateSymbolVisual, CarbohydrateSymbolParams } from '../visual/carbohydrate-symbol-mesh';
 import { CarbohydrateLinkVisual, CarbohydrateLinkParams } from '../visual/carbohydrate-link-cylinder';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
 
 export const CarbohydrateParams = {
     ...CarbohydrateSymbolParams,
diff --git a/src/mol-geo/representation/structure/representation/cartoon.ts b/src/mol-geo/representation/structure/representation/cartoon.ts
index e9934ed66376b1776b81cbdd43b30d88c6394797..3f5e915cd6ab562feccd2e6bf87811c63c9c85f3 100644
--- a/src/mol-geo/representation/structure/representation/cartoon.ts
+++ b/src/mol-geo/representation/structure/representation/cartoon.ts
@@ -13,9 +13,9 @@ import { MarkerAction } from '../../../geometry/marker-data';
 import { PolymerTraceVisual,  PolymerTraceParams } from '../visual/polymer-trace-mesh';
 import { PolymerGapVisual, PolymerGapParams } from '../visual/polymer-gap-cylinder';
 import { NucleotideBlockVisual, NucleotideBlockParams } from '../visual/nucleotide-block-mesh';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
 // import { PolymerDirectionVisual, DefaultPolymerDirectionProps } from '../visual/polymer-direction-wedge';
 
 export const CartoonParams = {
diff --git a/src/mol-geo/representation/structure/representation/distance-restraint.ts b/src/mol-geo/representation/structure/representation/distance-restraint.ts
index 5d460bb59c7b971ca1515950e80991f68436b007..7e683865197006a15c03dea03c4e3c2dd746dd5c 100644
--- a/src/mol-geo/representation/structure/representation/distance-restraint.ts
+++ b/src/mol-geo/representation/structure/representation/distance-restraint.ts
@@ -11,9 +11,9 @@ import { Task } from 'mol-task';
 import { Loci } from 'mol-model/loci';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { CrossLinkRestraintVisual, CrossLinkRestraintParams } from '../visual/cross-link-restraint-cylinder';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
 
 export const DistanceRestraintParams = {
     ...CrossLinkRestraintParams,
diff --git a/src/mol-geo/representation/structure/representation/molecular-surface.ts b/src/mol-geo/representation/structure/representation/molecular-surface.ts
index be412fc1ea8096999ffcee1aa20601da73984709..9a4fd1378bddf9db7322979a5d064a64d6ed13eb 100644
--- a/src/mol-geo/representation/structure/representation/molecular-surface.ts
+++ b/src/mol-geo/representation/structure/representation/molecular-surface.ts
@@ -14,9 +14,9 @@ import { PickingId } from '../../../geometry/picking';
 import { Task } from 'mol-task';
 import { GaussianWireframeVisual, GaussianWireframeParams } from '../visual/gaussian-surface-wireframe';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues, MultiSelectParam, SelectParam } from 'mol-view/parameter';
+import { paramDefaultValues, MultiSelectParam, SelectParam } from 'mol-util/parameter';
 import { GaussianDensityVolumeParams, GaussianDensityVolumeVisual } from '../visual/gaussian-density-volume';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 
 const VisualOptions = [['surface', 'Surface'], ['wireframe', 'Wireframe'], ['volume', 'Volume']] as [string, string][]
 
diff --git a/src/mol-geo/representation/structure/representation/point.ts b/src/mol-geo/representation/structure/representation/point.ts
index 09049bf3b4cb7a3abc76f7afa590d42f9aa881ca..2992e750372136140837430c8b448cb6c1ae1cbb 100644
--- a/src/mol-geo/representation/structure/representation/point.ts
+++ b/src/mol-geo/representation/structure/representation/point.ts
@@ -11,7 +11,7 @@ import { Structure } from 'mol-model/structure';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { Loci } from 'mol-model/loci';
 import { PickingId } from '../../../geometry/picking';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 export const PointParams = {
     ...ElementPointParams,
diff --git a/src/mol-geo/representation/structure/representation/spacefill.ts b/src/mol-geo/representation/structure/representation/spacefill.ts
index 740c240c7fd3b42e082e8ae12a3ea7b58f91b565..c79ece3e06d47525775ba60cdd35a3fbed168201 100644
--- a/src/mol-geo/representation/structure/representation/spacefill.ts
+++ b/src/mol-geo/representation/structure/representation/spacefill.ts
@@ -12,7 +12,7 @@ import { PickingId } from '../../../geometry/picking';
 import { MarkerAction } from '../../../geometry/marker-data';
 import { Loci } from 'mol-model/loci';
 import { getQualityProps } from '../../util';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 export const SpacefillParams = {
     ...ElementSphereParams
diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts
index 5e674479a1c2086eeb4475ca6b622c55282519e8..bef61d53306551b03c7e018873286aa8dbf67d03 100644
--- a/src/mol-geo/representation/structure/units-visual.ts
+++ b/src/mol-geo/representation/structure/units-visual.ts
@@ -22,7 +22,7 @@ import { updateRenderableState, Geometry } from '../../geometry/geometry';
 import { createColors } from '../../geometry/color-data';
 import { createSizes } from '../../geometry/size-data';
 import { Lines } from '../../geometry/lines/lines';
-import { MultiSelectParam, paramDefaultValues } from 'mol-view/parameter';
+import { MultiSelectParam, paramDefaultValues } from 'mol-util/parameter';
 import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 import { RenderableValues } from 'mol-gl/renderable/schema';
 
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
index a475a28892756d2649c146e53d07c48103008cbf..bfc6af645bae1db284644f5b6059b92cc80d7236 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
@@ -15,11 +15,11 @@ import { LocationIterator } from '../../../util/location-iterator';
 import { createLinkCylinderMesh, LinkCylinderProps, LinkCylinderParams } from './util/link';
 import { OrderedSet, Interval } from 'mol-data/int';
 import { ComplexMeshVisual } from '../complex-visual';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { LinkType } from 'mol-model/structure/model/types';
 import { BitFlags } from 'mol-util';
 import { UnitsMeshParams } from '../units-visual';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 // TODO create seperate visual
 // for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) {
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
index 15d4f0b765b0adb7d1cef23de5617697800a60b4..14e275795deb84816c8e2f1624eb9a52f3b52908 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
@@ -16,14 +16,14 @@ import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/struct
 import { LocationIterator } from '../../../util/location-iterator';
 import { OrderedSet, Interval } from 'mol-data/int';
 import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { addSphere } from '../../../geometry/mesh/builder/sphere';
 import { Box, PerforatedBox } from '../../../primitive/box';
 import { OctagonalPyramid, PerforatedOctagonalPyramid } from '../../../primitive/pyramid';
 import { Star } from '../../../primitive/star';
 import { Octahedron, PerforatedOctahedron } from '../../../primitive/octahedron';
 import { DiamondPrism, PentagonalPrism, HexagonalPrism } from '../../../primitive/prism';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 const t = Mat4.identity()
 const sVec = Vec3.zero()
diff --git a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
index 43764073b01327ad726ad6f9e333133bf6879c1d..703feccb4b2f5c027043e7108c3f0c7f4d3fa390 100644
--- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
@@ -15,10 +15,10 @@ import { Loci, EmptyLoci } from 'mol-model/loci';
 import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual';
 import { LocationIterator } from '../../../util/location-iterator';
 import { Interval } from 'mol-data/int';
-import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { BitFlags } from 'mol-util';
 import { LinkType } from 'mol-model/structure/model/types';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 async function createCrossLinkRestraintCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) {
 
diff --git a/src/mol-geo/representation/structure/visual/element-point.ts b/src/mol-geo/representation/structure/visual/element-point.ts
index e6fd797016cc0d882892cf49f4d73ed3e4545aef..6b25c8608d614720571911ae2718b0513507b33f 100644
--- a/src/mol-geo/representation/structure/visual/element-point.ts
+++ b/src/mol-geo/representation/structure/visual/element-point.ts
@@ -9,11 +9,11 @@ import { RuntimeContext } from 'mol-task'
 import { UnitsVisual, VisualUpdateState } from '..';
 import { getElementLoci, StructureElementIterator, markElement } from './util/element';
 import { Vec3 } from 'mol-math/linear-algebra';
-import { SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size';
+import { SizeThemeOptions, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { UnitsPointsVisual, UnitsPointsParams } from '../units-visual';
 import { Points } from '../../../geometry/points/points';
 import { PointsBuilder } from '../../../geometry/points/points-builder';
-import { SelectParam, NumberParam, BooleanParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, BooleanParam, paramDefaultValues } from 'mol-util/parameter';
 
 export const ElementPointParams = {
     ...UnitsPointsParams,
diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-geo/representation/structure/visual/element-sphere.ts
index 5913a0e4a64dd7f8e238dde5a2fcb16b49c86e18..baa54242959326bfdfe41234306c24ea4fcc5eae 100644
--- a/src/mol-geo/representation/structure/visual/element-sphere.ts
+++ b/src/mol-geo/representation/structure/visual/element-sphere.ts
@@ -8,8 +8,8 @@
 import { UnitsVisual, VisualUpdateState } from '..';
 import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
-import { NumberParam, paramDefaultValues, SelectParam } from 'mol-view/parameter';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { NumberParam, paramDefaultValues, SelectParam } from 'mol-util/parameter';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 
 export const ElementSphereParams = {
     ...UnitsMeshParams,
diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts
index 9a26d96019acfd67fbfe01967205328cf3bc0fc1..7ff641e9125c1b8070a3d260389e99fa6da11b14 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts
+++ b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts
@@ -13,9 +13,9 @@ import { Vec3 } from 'mol-math/linear-algebra';
 import { UnitsPointsVisual, UnitsPointsParams } from '../units-visual';
 import { Points } from '../../../geometry/points/points';
 import { PointsBuilder } from '../../../geometry/points/points-builder';
-import { SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size';
+import { SizeThemeOptions, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density';
-import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-view/parameter';
+import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-util/parameter';
 
 export const GaussianDensityPointParams = {
     ...UnitsPointsParams,
diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts b/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts
index 94bcd294a930ba8498e324a9eea043890225a34b..912c07dff46006c4f74baebb03f9ef1c38257ad2 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts
+++ b/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts
@@ -10,7 +10,7 @@ import { RuntimeContext } from 'mol-task'
 import { UnitsDirectVolumeVisual, UnitsDirectVolumeParams } from '../units-visual';
 import { StructureElementIterator, getElementLoci, markElement } from './util/element';
 import { GaussianDensityProps, GaussianDensityParams, computeUnitGaussianDensityTexture } from 'mol-model/structure/structure/unit/gaussian-density';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 import { DirectVolume } from '../../../geometry/direct-volume/direct-volume';
 
 async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> {
diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts
index 043f8dc93995af335aa768ec90f8adec6470ebc4..8faf356ab1290a11f262fed6744dba611f506e89 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts
@@ -12,7 +12,7 @@ import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
 import { StructureElementIterator, getElementLoci, markElement } from './util/element';
 import { computeMarchingCubesMesh } from '../../../util/marching-cubes/algorithm';
 import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 async function createGaussianSurfaceMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> {
     const { smoothness } = props
diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts
index 3d1da6e79ce63dee34a04cda3b393b5d0c22fcf1..0bb363663b5e405b9deb8fd93c4e8118dbb15cda 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts
+++ b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts
@@ -12,8 +12,8 @@ import { StructureElementIterator, getElementLoci, markElement } from './util/el
 import { computeMarchingCubesLines } from '../../../util/marching-cubes/algorithm';
 import { Lines } from '../../../geometry/lines/lines';
 import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density';
-import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-view/parameter';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-util/parameter';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 
 async function createGaussianWireframe(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, lines?: Lines): Promise<Lines> {
     const { smoothness } = props
diff --git a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
index 5503cae068a2afa4d51fa9ac0ff3e1c746234494..796adcb04eef4780e676e48561a1db2e92f8da02 100644
--- a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
@@ -14,9 +14,9 @@ import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual';
 import { Interval } from 'mol-data/int';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { BitFlags } from 'mol-util';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) {
     const links = structure.links
diff --git a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
index 005799c8189e223b89800cc327a7049dc35da9fd..c3569027b16c0abeca7e955535d7cec0e6ddd037 100644
--- a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
@@ -15,9 +15,9 @@ import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
 import { Interval } from 'mol-data/int';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { BitFlags } from 'mol-util';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) {
     if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
diff --git a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts
index 5e778b020dc8c656cc944c2a5735ec216a5e730d..1dd4bc8b36398ea5f115d31e38912ec30216c510 100644
--- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts
@@ -17,7 +17,7 @@ import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
 import { addCylinder } from '../../../geometry/mesh/builder/cylinder';
 import { Box } from '../../../primitive/box';
 import { NucleotideLocationIterator, markNucleotideElement, getNucleotideElementLoci } from './util/nucleotide';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 const p1 = Vec3.zero()
 const p2 = Vec3.zero()
diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts
index 50aea2a8b80e9815a537986803aafeb3b54b4d71..62860a718cd4e68bd14623792b8f5e3587aa369e 100644
--- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts
@@ -13,11 +13,11 @@ import { PolymerBackboneIterator } from './util/polymer';
 import { getElementLoci, markElement, StructureElementIterator } from './util/element';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
-import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { CylinderProps } from '../../../primitive/cylinder';
 import { OrderedSet } from 'mol-data/int';
 import { addCylinder } from '../../../geometry/mesh/builder/cylinder';
-import { paramDefaultValues, NumberParam, SelectParam } from 'mol-view/parameter';
+import { paramDefaultValues, NumberParam, SelectParam } from 'mol-util/parameter';
 
 export const PolymerBackboneCylinderParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
diff --git a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts
index cce1eb9b6c33c0755a32db30f5ebac881d3e23aa..1601fca4bf7ced098693fe44c2e093f34e1f559a 100644
--- a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts
+++ b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts
@@ -13,9 +13,9 @@ import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment,
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { Wedge } from '../../../primitive/wedge';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 const t = Mat4.identity()
 const sVec = Vec3.zero()
diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
index e8b3a62b6151dd89001ad3a1b6246c3d08a7fb01..98ace9ba4bacf9e9d797f187406339fafebb691d 100644
--- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
+++ b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
@@ -12,11 +12,11 @@ import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
 import { PolymerGapIterator, PolymerGapLocationIterator, markPolymerGapElement, getPolymerGapElementLoci } from './util/polymer';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
-import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { CylinderProps } from '../../../primitive/cylinder';
 import { addSphere } from '../../../geometry/mesh/builder/sphere';
 import { addFixedCountDashedCylinder } from '../../../geometry/mesh/builder/cylinder';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 import { LinkCylinderParams } from './util/link';
 
 const segmentCount = 10
diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts
index e5380b1bfaf50a749431485aa8dc0e32baed1553..4a7bc8dde31d8f678ab5c899bdf296749549299e 100644
--- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts
+++ b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts
@@ -12,10 +12,10 @@ import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
 import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer';
 import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
-import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { addSheet } from '../../../geometry/mesh/builder/sheet';
 import { addTube } from '../../../geometry/mesh/builder/tube';
-import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 export const PolymerTraceMeshParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions),
diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-geo/representation/structure/visual/util/element.ts
index 76dfc4a5079bc27e2584b332d41c519a9de01336..b2205660c510bcf2df4894e6757f9b457872dde8 100644
--- a/src/mol-geo/representation/structure/visual/util/element.ts
+++ b/src/mol-geo/representation/structure/visual/util/element.ts
@@ -13,7 +13,7 @@ import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { Interval, OrderedSet } from 'mol-data/int';
 import { PickingId } from '../../../../geometry/picking';
-import { SizeTheme, SizeThemeName } from 'mol-view/theme/size';
+import { SizeTheme, SizeThemeName } from 'mol-canvas3d/theme/size';
 import { LocationIterator } from '../../../../util/location-iterator';
 import { addSphere } from '../../../../geometry/mesh/builder/sphere';
 
diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts
index 6cdbae8aba636308fa4a0796bc0a94a42c834548..0c2eede028c9c8ccb182d8658ef357e5f1ce4ccf 100644
--- a/src/mol-geo/representation/structure/visual/util/link.ts
+++ b/src/mol-geo/representation/structure/visual/util/link.ts
@@ -9,12 +9,12 @@ import { RuntimeContext } from 'mol-task';
 import { Mesh } from '../../../../geometry/mesh/mesh';
 import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder';
 import { LinkType } from 'mol-model/structure/model/types';
-import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size';
+import { SizeThemeName, SizeThemeOptions } from 'mol-canvas3d/theme/size';
 import { CylinderProps } from '../../../../primitive/cylinder';
 import { LocationIterator } from '../../../../util/location-iterator';
 import { Unit, StructureElement, Structure, Link } from 'mol-model/structure';
 import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from '../../../../geometry/mesh/builder/cylinder';
-import { SelectParam, RangeParam, NumberParam, paramDefaultValues } from 'mol-view/parameter';
+import { SelectParam, RangeParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
 
 export const LinkCylinderParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
diff --git a/src/mol-geo/representation/volume/direct-volume.ts b/src/mol-geo/representation/volume/direct-volume.ts
index 5819bfa9b3a6f69b2d27b7cb55c35f7cc1b0a0ec..49d12ef2ae936570befdab559c17c033cd70112a 100644
--- a/src/mol-geo/representation/volume/direct-volume.ts
+++ b/src/mol-geo/representation/volume/direct-volume.ts
@@ -12,7 +12,7 @@ import { PickingId } from '../../geometry/picking';
 import { MarkerAction } from '../../geometry/marker-data';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { createRenderableState, updateRenderableState, Geometry } from '../../geometry/geometry';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Box3D } from 'mol-math/geometry';
diff --git a/src/mol-geo/representation/volume/index.ts b/src/mol-geo/representation/volume/index.ts
index 2bbceed74d941ac56213cf044a60f8129d5e322e..dcb95d81aa6007052dbf12b82586e119dfb6c681 100644
--- a/src/mol-geo/representation/volume/index.ts
+++ b/src/mol-geo/representation/volume/index.ts
@@ -11,7 +11,7 @@ import { PickingId } from '../../geometry/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../geometry/marker-data';
 import { Geometry } from '../../geometry/geometry';
-import { paramDefaultValues } from 'mol-view/parameter';
+import { paramDefaultValues } from 'mol-util/parameter';
 
 export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { }
 
diff --git a/src/mol-geo/representation/volume/isosurface-mesh.ts b/src/mol-geo/representation/volume/isosurface-mesh.ts
index e6c95184044c7b29f6ed4e91e3c12325e64e646f..acff269e697040063011363c958f61be524e8f26 100644
--- a/src/mol-geo/representation/volume/isosurface-mesh.ts
+++ b/src/mol-geo/representation/volume/isosurface-mesh.ts
@@ -18,7 +18,7 @@ import { LocationIterator } from '../../util/location-iterator';
 import { NullLocation } from 'mol-model/location';
 import { createIdentityTransform } from '../../geometry/transform-data';
 import { createRenderableState, updateRenderableState } from '../../geometry/geometry';
-import { paramDefaultValues, RangeParam } from 'mol-view/parameter';
+import { paramDefaultValues, RangeParam } from 'mol-util/parameter';
 import { ValueCell } from 'mol-util';
 
 export async function createVolumeSurface(ctx: RuntimeContext, volume: VolumeData, isoValueAbsolute: number, mesh?: Mesh) {
diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts
index ab7feffcc3e4fa8df4bd6047f85fed95a005d47b..6ede20f9997f0ea08e4b64b06dc1dacb73883dfc 100644
--- a/src/mol-gl/_spec/renderer.spec.ts
+++ b/src/mol-gl/_spec/renderer.spec.ts
@@ -6,7 +6,7 @@
 
 import { createGl } from './gl.shim';
 
-import { PerspectiveCamera } from 'mol-view/camera/perspective';
+import { PerspectiveCamera } from 'mol-canvas3d/camera/perspective';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { ValueCell } from 'mol-util';
 
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index 35a940f89178885396d31114922b72f86d9056f4..3437f75c1539900aa7ac0a0574f1e215585294ce 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -5,8 +5,8 @@
  */
 
 // import { Vec3, Mat4 } from 'mol-math/linear-algebra'
-import { Viewport } from 'mol-view/camera/util';
-import { Camera } from 'mol-view/camera/base';
+import { Viewport } from 'mol-canvas3d/camera/util';
+import { Camera } from 'mol-canvas3d/camera/base';
 
 import Scene from './scene';
 import { Context, createImageData } from './webgl/context';
diff --git a/src/mol-model/structure/structure/unit/gaussian-density.ts b/src/mol-model/structure/structure/unit/gaussian-density.ts
index a5d4d0681972dc13e3a20449cd8712a594489975..e79797d220cdb6ae8114f2f9bd8e918896220b7b 100644
--- a/src/mol-model/structure/structure/unit/gaussian-density.ts
+++ b/src/mol-model/structure/structure/unit/gaussian-density.ts
@@ -5,11 +5,11 @@
  */
 
 import { Unit, StructureElement, ElementIndex } from 'mol-model/structure';
-import { SizeTheme } from 'mol-view/theme/size';
+import { SizeTheme } from 'mol-canvas3d/theme/size';
 import { GaussianDensity } from 'mol-math/geometry/gaussian-density';
 import { Task, RuntimeContext } from 'mol-task';
 import { DensityData } from 'mol-math/geometry';
-import { NumberParam, paramDefaultValues, BooleanParam, ValueParam } from 'mol-view/parameter';
+import { NumberParam, paramDefaultValues, BooleanParam, ValueParam } from 'mol-util/parameter';
 import { Context } from 'mol-gl/webgl/context';
 import { GaussianDensityTexture } from 'mol-math/geometry/gaussian-density/gpu';
 import { Texture } from 'mol-gl/webgl/texture';
diff --git a/src/mol-state/context/context.ts b/src/mol-plugin/index.ts
similarity index 81%
rename from src/mol-state/context/context.ts
rename to src/mol-plugin/index.ts
index b7fd34c4cb9e8389d55489c8b0b5c8b8330307ab..7c7fe83382a744be37fe5118239b71702aebc60d 100644
--- a/src/mol-state/context/context.ts
+++ b/src/mol-plugin/index.ts
@@ -4,6 +4,4 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-export interface StateContext {
-
-}
\ No newline at end of file
+// TODO
\ No newline at end of file
diff --git a/src/mol-state/context.ts b/src/mol-state/context.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bb04a1de101777951c6c67e0cdb8b5f88908c3fe
--- /dev/null
+++ b/src/mol-state/context.ts
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { Subject } from 'rxjs'
+import { StateObject } from './object';
+import { Transform } from './tree/transform';
+
+interface StateContext {
+    events: {
+        object: {
+            stateChanged: Subject<{ ref: Transform.Ref }>,
+            propsChanged: Subject<{ ref: Transform.Ref, newProps: unknown }>,
+            updated: Subject<{ ref: Transform.Ref }>,
+            replaced: Subject<{ ref: Transform.Ref, old?: StateObject }>,
+            created: Subject<{ ref: Transform.Ref }>,
+            removed: Subject<{ ref: Transform.Ref }>,
+        },
+        warn: Subject<string>
+    },
+    globalContext: unknown,
+    defaultObjectProps: unknown
+}
+
+namespace StateContext {
+    export function create(params: { globalContext: unknown, defaultObjectProps: unknown }): StateContext {
+        return {
+            events: {
+                object: {
+                    stateChanged: new Subject(),
+                    propsChanged: new Subject(),
+                    updated: new Subject(),
+                    replaced: new Subject(),
+                    created: new Subject(),
+                    removed: new Subject()
+                },
+                warn: new Subject()
+            },
+            globalContext: params.globalContext,
+            defaultObjectProps: params.defaultObjectProps
+        }
+    }
+}
+
+export { StateContext }
\ No newline at end of file
diff --git a/src/mol-state/event/dispatcher.ts b/src/mol-state/event/dispatcher.ts
deleted file mode 100644
index 32dcb9a0516c288ed83911bba462598e0372cb0d..0000000000000000000000000000000000000000
--- a/src/mol-state/event/dispatcher.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-export interface EventDispatcher {
-    // TODO
-}
\ No newline at end of file
diff --git a/src/mol-state/event/event.ts b/src/mol-state/event/event.ts
deleted file mode 100644
index 32dcb9a0516c288ed83911bba462598e0372cb0d..0000000000000000000000000000000000000000
--- a/src/mol-state/event/event.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-export interface EventDispatcher {
-    // TODO
-}
\ No newline at end of file
diff --git a/src/mol-state/index.ts b/src/mol-state/index.ts
index 9dd0621de618c2a038d9e82f08cf9e6be0f0f843..0ebc69a6980415c57a8dcfe28fab11e0ab8d66ff 100644
--- a/src/mol-state/index.ts
+++ b/src/mol-state/index.ts
@@ -2,4 +2,12 @@
  * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
- */
\ No newline at end of file
+ */
+
+export * from './object'
+export * from './state'
+export * from './transformer'
+export * from './tree'
+export * from './context'
+export * from './tree/transform'
+export * from './tree/selection'
\ No newline at end of file
diff --git a/src/mol-state/object.ts b/src/mol-state/object.ts
index 38389e2a36c68f7c0404ae3609d85d1248b46122..61f9142cf8edb433173664ec844742edc2f5b744 100644
--- a/src/mol-state/object.ts
+++ b/src/mol-state/object.ts
@@ -16,12 +16,6 @@ export interface StateObject<P = unknown, D = unknown> {
 }
 
 export namespace StateObject {
-    // export type TypeOf<T>
-    //     = T extends StateObject<infer X> ? [X]
-    //     : T extends [StateObject<infer X>] ? [X]
-    //     : T extends [StateObject<infer X>, StateObject<infer Y>] ? [X, Y]
-    //     : unknown[];
-
     export enum StateType {
         // The object has been successfully created
         Ok,
@@ -52,9 +46,11 @@ export namespace StateObject {
         }
     }
 
-    export interface Wrapped {
-        obj: StateObject,
+    export interface Node {
         state: StateType,
+        props: unknown,
+        errorText?: string,
+        obj?: StateObject,
         version: string
     }
 }
\ No newline at end of file
diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts
index 6f3fa1c456c776f6a7aa9324e802f0967e876994..b586e5c2cc4de70b4115bf2bfe505e398f451160 100644
--- a/src/mol-state/state.ts
+++ b/src/mol-state/state.ts
@@ -5,79 +5,97 @@
  */
 
 import { StateObject } from './object';
-import { TransformTree } from './tree/tree';
+import { StateTree } from './tree';
 import { Transform } from './tree/transform';
-import { Map as ImmutableMap } from 'immutable';
-// import { StateContext } from './context/context';
 import { ImmutableTree } from './util/immutable-tree';
 import { Transformer } from './transformer';
-import { Task } from 'mol-task';
+import { StateContext } from './context';
+import { UUID } from 'mol-util';
+import { RuntimeContext, Task } from 'mol-task';
 
-export interface State<ObjectProps = unknown> {
-    definition: State.Definition<ObjectProps>,
-    objects: State.Objects
+export interface State {
+    tree: StateTree,
+    objects: State.Objects,
+    context: StateContext
 }
 
 export namespace State {
-    export type ObjectProps<P> = ImmutableMap<Transform.Ref, P>
-    export type Objects = Map<Transform.Ref, StateObject.Wrapped>
+    export type Ref = Transform.Ref
+    export type Objects = Map<Ref, StateObject.Node>
 
-    export interface Definition<P = unknown> {
-        tree: TransformTree,
-        // things like object visibility
-        props: ObjectProps<P>
-    }
-
-    export function create(): State {
-        const tree = TransformTree.create();
+    export function create(params?: { globalContext?: unknown, defaultObjectProps: unknown }) {
+        const tree = StateTree.create();
         const objects: Objects = new Map();
         const root = tree.getValue(tree.rootRef)!;
+        const defaultObjectProps = (params && params.defaultObjectProps) || { }
 
-        objects.set(tree.rootRef, { obj: void 0 as any, state: StateObject.StateType.Ok, version: root.version });
+        objects.set(tree.rootRef, { obj: void 0 as any, state: StateObject.StateType.Ok, version: root.version, props: { ...defaultObjectProps } });
 
         return {
-            definition: {
-                tree,
-                props: ImmutableMap()
-            },
-            objects
+            tree,
+            objects,
+            context: StateContext.create({
+                globalContext: params && params.globalContext,
+                defaultObjectProps
+            })
         };
     }
 
-    export async function update<P>(state: State<P>, tree: TransformTree, props?: ObjectProps<P>): Promise<State<P>> {
-        const roots = findUpdateRoots(state.objects, tree);
-        const deletes = findDeletes(state.objects, tree);
+    export function update(state: State, tree: StateTree): Task<State> {
+        return Task.create('Update Tree', taskCtx => {
+            const ctx: UpdateContext = {
+                stateCtx: state.context,
+                taskCtx,
+                oldTree: state.tree,
+                tree: tree,
+                objects: state.objects
+            };
+            return _update(ctx);
+        })
+    }
+
+    async function _update(ctx: UpdateContext): Promise<State> {
+        const roots = findUpdateRoots(ctx.objects, ctx.tree);
+        const deletes = findDeletes(ctx);
         for (const d of deletes) {
-            state.objects.delete(d);
+            ctx.objects.delete(d);
+            ctx.stateCtx.events.object.removed.next({ ref: d });
         }
 
-        console.log('roots', roots);
+        initObjectState(ctx, roots);
+
         for (const root of roots) {
-            await updateSubtree(state.definition.tree, tree, state.objects, root);
+            await updateSubtree(ctx, root);
         }
 
         return {
-            definition: { tree, props: props || state.definition.props },
-            objects: state.objects
+            tree: ctx.tree,
+            objects: ctx.objects,
+            context: ctx.stateCtx
         };
     }
 
-    function findUpdateRoots(objects: Objects, tree: TransformTree) {
-        console.log(tree);
+    interface UpdateContext {
+        stateCtx: StateContext,
+        taskCtx: RuntimeContext,
+        oldTree: StateTree,
+        tree: StateTree,
+        objects: Objects
+    }
+
+    function findUpdateRoots(objects: Objects, tree: StateTree) {
         const findState = {
-            roots: [] as Transform.Ref[],
+            roots: [] as Ref[],
             objects
         };
 
         ImmutableTree.doPreOrder(tree, tree.nodes.get(tree.rootRef)!, findState, (n, _, s) => {
             if (!s.objects.has(n.ref)) {
-                console.log('missing', n.ref);
                 s.roots.push(n.ref);
                 return false;
             }
             const o = s.objects.get(n.ref)!;
             if (o.version !== n.value.version) {
-                console.log('diff version', n.ref, n.value.version, o.version);
                 s.roots.push(n.ref);
                 return false;
             }
@@ -88,66 +106,153 @@ export namespace State {
         return findState.roots;
     }
 
-    function findDeletes(objects: Objects, tree: TransformTree): Transform.Ref[] {
-        // TODO
-        return [];
+    function findDeletes(ctx: UpdateContext): Ref[] {
+        // TODO: do this in some sort of "tree order"?
+        const deletes: Ref[] = [];
+        const keys = ctx.objects.keys();
+        while (true) {
+            const key = keys.next();
+            if (key.done) break;
+            if (!ctx.tree.nodes.has(key.value)) deletes.push(key.value);
+        }
+        return deletes;
+    }
+
+    function setObjectState(ctx: UpdateContext, ref: Ref, state: StateObject.StateType, errorText?: string) {
+        let changed = false;
+        if (ctx.objects.has(ref)) {
+            const obj = ctx.objects.get(ref)!;
+            changed = obj.state !== state;
+            obj.state = state;
+            obj.errorText = errorText;
+        } else {
+            const obj = { state, version: UUID.create(), errorText, props: { ...ctx.stateCtx.defaultObjectProps } };
+            ctx.objects.set(ref, obj);
+            changed = true;
+        }
+        if (changed) ctx.stateCtx.events.object.stateChanged.next({ ref });
     }
 
-    function findParent(tree: TransformTree, objects: Objects, root: Transform.Ref, types: { type: StateObject.Type }[]): StateObject {
+    function _initVisitor(t: ImmutableTree.Node<Transform>, _: any, ctx: UpdateContext) {
+        setObjectState(ctx, t.ref, StateObject.StateType.Pending);
+    }
+    /** Return "resolve set" */
+    function initObjectState(ctx: UpdateContext, roots: Ref[]) {
+        for (const root of roots) {
+            ImmutableTree.doPreOrder(ctx.tree, ctx.tree.nodes.get(root), ctx, _initVisitor);
+        }
+    }
+
+    function doError(ctx: UpdateContext, ref: Ref, errorText: string) {
+        setObjectState(ctx, ref, StateObject.StateType.Error, errorText);
+        const wrap = ctx.objects.get(ref)!;
+        if (wrap.obj) {
+            ctx.stateCtx.events.object.removed.next({ ref });
+            wrap.obj = void 0;
+        }
+
+        const children = ctx.tree.nodes.get(ref)!.children.values();
+        while (true) {
+            const next = children.next();
+            if (next.done) return;
+            doError(ctx, next.value, 'Parent node contains error.');
+        }
+    }
+
+    function findParent(tree: StateTree, objects: Objects, root: Ref, types: { type: StateObject.Type }[]): StateObject {
         let current = tree.nodes.get(root)!;
-        console.log('finding', types.map(t => t.type.kind));
         while (true) {
             current = tree.nodes.get(current.parent)!;
-            if (current.ref === tree.rootRef) return objects.get(tree.rootRef)!.obj;
-            const obj = objects.get(current.ref)!.obj;
-            console.log('current', obj.type.kind);
-            for (const t of types) if (obj.type === t.type) return objects.get(current.ref)!.obj;
+            if (current.ref === tree.rootRef) {
+                return objects.get(tree.rootRef)!.obj!;
+            }
+            const obj = objects.get(current.ref)!.obj!;
+            for (const t of types) if (obj.type === t.type) return objects.get(current.ref)!.obj!;
         }
     }
 
-    async function updateSubtree(oldTree: TransformTree, tree: TransformTree, objects: Objects, root: Transform.Ref) {
-        await updateNode(oldTree, tree, objects, root);
-        const children = tree.nodes.get(root)!.children.values();
+    async function updateSubtree(ctx: UpdateContext, root: Ref) {
+        setObjectState(ctx, root, StateObject.StateType.Processing);
+
+        try {
+            const update = await updateNode(ctx, root);
+            setObjectState(ctx, root, StateObject.StateType.Ok);
+            if (update.action === 'created') {
+                ctx.stateCtx.events.object.created.next({ ref: root });
+            } else if (update.action === 'updated') {
+                ctx.stateCtx.events.object.updated.next({ ref: root });
+            } else if (update.action === 'replaced') {
+                ctx.stateCtx.events.object.replaced.next({ ref: root, old: update.old });
+            }
+        } catch (e) {
+            doError(ctx, root, '' + e);
+            return;
+        }
+
+        const children = ctx.tree.nodes.get(root)!.children.values();
         while (true) {
             const next = children.next();
             if (next.done) return;
-            await updateSubtree(oldTree, tree, objects, next.value);
+            await updateSubtree(ctx, next.value);
         }
     }
 
-    async function updateNode(oldTree: TransformTree, tree: TransformTree, objects: Objects, root: Transform.Ref) {
-        const transform = tree.getValue(root)!;
-        const parent = findParent(tree, objects, root, transform.transformer.definition.from);
-        console.log('parent', parent ? parent.ref : 'undefined')
-        if (!oldTree.nodes.has(transform.ref) || !objects.has(transform.ref)) {
-            console.log('creating...', transform.transformer.id, oldTree.nodes.has(transform.ref), objects.has(transform.ref));
-            const obj = await createObject(transform.transformer, parent, transform.params);
-            obj.ref = transform.ref;
-            objects.set(root, { obj, state: StateObject.StateType.Ok, version: transform.version });
+    async function updateNode(ctx: UpdateContext, currentRef: Ref) {
+        const { oldTree, tree, objects } = ctx;
+        const transform = tree.getValue(currentRef)!;
+        const parent = findParent(tree, objects, currentRef, transform.transformer.definition.from);
+        // console.log('parent', transform.transformer.id, transform.transformer.definition.from[0].type, parent ? parent.ref : 'undefined')
+        if (!oldTree.nodes.has(currentRef) || !objects.has(currentRef)) {
+            // console.log('creating...', transform.transformer.id, oldTree.nodes.has(currentRef), objects.has(currentRef));
+            const obj = await createObject(ctx, transform.transformer, parent, transform.params);
+            obj.ref = currentRef;
+            objects.set(currentRef, {
+                obj,
+                state: StateObject.StateType.Ok,
+                version: transform.version,
+                props: { ...ctx.stateCtx.defaultObjectProps, ...transform.defaultProps }
+            });
+            return { action: 'created' };
         } else {
-            console.log('updating...', transform.transformer.id);
-            const current = objects.get(transform.ref)!.obj;
-            const oldParams = oldTree.getValue(transform.ref)!.params;
-            await updateObject(transform.transformer, parent, current, oldParams, transform.params);
-            const obj = objects.get(root)!;
-            obj.version = transform.version;
+            // console.log('updating...', transform.transformer.id);
+            const current = objects.get(currentRef)!;
+            const oldParams = oldTree.getValue(currentRef)!.params;
+            switch (await updateObject(ctx, transform.transformer, parent, current.obj!, oldParams, transform.params)) {
+                case Transformer.UpdateResult.Recreate: {
+                    const obj = await createObject(ctx, transform.transformer, parent, transform.params);
+                    obj.ref = currentRef;
+                    objects.set(currentRef, {
+                        obj,
+                        state: StateObject.StateType.Ok,
+                        version: transform.version,
+                        props: { ...ctx.stateCtx.defaultObjectProps, ...current.props, ...transform.defaultProps }
+                    });
+                    return { action: 'replaced', old: current.obj! };
+                }
+                case Transformer.UpdateResult.Updated:
+                    current.version = transform.version;
+                    current.props = { ...ctx.stateCtx.defaultObjectProps, ...current.props, ...transform.defaultProps };
+                    return { action: 'updated' };
+                default:
+                    // TODO check if props need to be updated
+                    return { action: 'none' };
+            }
         }
     }
 
-    async function runTask<A>(t: A | Task<A>): Promise<A> {
-        if ((t as any).run) return await (t as Task<A>).run();
-        return t as A;
+    function runTask<T>(t: T | Task<T>, ctx: RuntimeContext) {
+        if (typeof (t as any).run === 'function') return (t as Task<T>).runInContext(ctx);
+        return t as T;
     }
 
-    function createObject(transformer: Transformer, parent: StateObject, params: any) {
-        return runTask(transformer.definition.apply(parent, params, 0 as any));
+    function createObject(ctx: UpdateContext, transformer: Transformer, a: StateObject, params: any) {
+        return runTask(transformer.definition.apply({ a, params }, ctx.stateCtx.globalContext), ctx.taskCtx);
     }
 
-    async function updateObject(transformer: Transformer, parent: StateObject, obj: StateObject, oldParams: any, params: any) {
+    async function updateObject(ctx: UpdateContext, transformer: Transformer, a: StateObject, b: StateObject, oldParams: any, newParams: any) {
         if (!transformer.definition.update) {
-            // TODO
-            throw 'nyi';
+            return Transformer.UpdateResult.Recreate;
         }
-        return transformer.definition.update!(parent, oldParams, obj, params, 0 as any);
+        return runTask(transformer.definition.update({ a, oldParams, b, newParams }, ctx.stateCtx.globalContext), ctx.taskCtx);
     }
 }
diff --git a/src/mol-state/transformer.ts b/src/mol-state/transformer.ts
index 9f94340d18785227fefab4cdfbd9c1000f8792bb..701085fff0adf0b6ca0d63357ed78e2fd9f354b0 100644
--- a/src/mol-state/transformer.ts
+++ b/src/mol-state/transformer.ts
@@ -6,11 +6,11 @@
 
 import { Task } from 'mol-task';
 import { StateObject } from './object';
-import { TransformContext } from './tree/context';
 import { Transform } from './tree/transform';
 
 export interface Transformer<A extends StateObject = StateObject, B extends StateObject = StateObject, P = unknown> {
     apply(params?: P, props?: Partial<Transform.Props>): Transform<A, B, P>,
+    readonly namespace: string,
     readonly id: Transformer.Id,
     readonly definition: Transformer.Definition<A, B, P>
 }
@@ -21,9 +21,22 @@ export namespace Transformer {
     export type To<T extends Transformer<any, any, any>> = T extends Transformer<any, infer B, any> ? B : unknown;
     export type ControlsFor<Props> = { [P in keyof Props]?: any }
 
+    export interface ApplyParams<A extends StateObject = StateObject, P = unknown> {
+        a: A,
+        params: P
+    }
+
+    export interface UpdateParams<A extends StateObject = StateObject, B extends StateObject = StateObject, P = unknown> {
+        a: A,
+        b: B,
+        oldParams: P,
+        newParams: P
+    }
+
+    export enum UpdateResult { Unchanged, Updated, Recreate }
+
     export interface Definition<A extends StateObject = StateObject, B extends StateObject = StateObject, P = unknown> {
         readonly name: string,
-        readonly namespace?: string,
         readonly from: { type: StateObject.Type }[],
         readonly to: { type: StateObject.Type }[],
 
@@ -31,31 +44,29 @@ export namespace Transformer {
          * Apply the actual transformation. It must be pure (i.e. with no side effects).
          * Returns a task that produces the result of the result directly.
          */
-        apply(a: A, params: P, context: TransformContext): Task<B> | B,
+        apply(params: ApplyParams<A, P>, globalCtx: unknown): Task<B> | B,
 
         /**
          * Attempts to update the entity in a non-destructive way.
          * For example changing a color scheme of a visual does not require computing new geometry.
          * Return/resolve to undefined if the update is not possible.
-         *
-         * The ability to resolve the task to undefined is present for "async updates" (i.e. containing an ajax call).
          */
-        update?(a: A, oldParams: P, b: B, newParams: P, context: TransformContext): Task<B | undefined> | B | undefined,
+        update?(params: UpdateParams<A, B, P>, globalCtx: unknown): Task<UpdateResult> | UpdateResult,
 
         /** Check the parameters and return a list of errors if the are not valid. */
-        defaultParams?(a: A, context: TransformContext): P,
+        defaultParams?(a: A, globalCtx: unknown): P,
 
         /** Specify default control descriptors for the parameters */
-        defaultControls?(a: A, context: TransformContext): Transformer.ControlsFor<P>,
+        defaultControls?(a: A, globalCtx: unknown): Transformer.ControlsFor<P>,
 
         /** Check the parameters and return a list of errors if the are not valid. */
-        validateParams?(a: A, params: P, context: TransformContext): string[] | undefined,
+        validateParams?(a: A, params: P, globalCtx: unknown): string[] | undefined,
 
         /** Optional custom parameter equality. Use deep structural equal by default. */
         areParamsEqual?(oldParams: P, newParams: P): boolean,
 
         /** Test if the transform can be applied to a given node */
-        isApplicable?(a: A, context: TransformContext): boolean,
+        isApplicable?(a: A, globalCtx: unknown): boolean,
 
         /** By default, returns true */
         isSerializable?(params: P): { isSerializable: true } | { isSerializable: false; reason: string },
@@ -66,12 +77,6 @@ export namespace Transformer {
 
     const registry = new Map<Id, Transformer>();
 
-    function typeToString(a: { type: StateObject.Type }[]) {
-        if (!a.length) return '()';
-        if (a.length === 1) return a[0].type.kind;
-        return `(${a.map(t => t.type.kind).join(' | ')})`;
-    }
-
     export function get(id: string): Transformer {
         const t = registry.get(id as Id);
         if (!t) {
@@ -81,8 +86,8 @@ export namespace Transformer {
     }
 
     export function create<A extends StateObject, B extends StateObject, P>(namespace: string, definition: Definition<A, B, P>) {
-        const { from, to, name } = definition;
-        const id = `${namespace}.${name} :: ${typeToString(from)} -> ${typeToString(to)}` as Id;
+        const { name } = definition;
+        const id = `${namespace}.${name}` as Id;
 
         if (registry.has(id)) {
             throw new Error(`A transform with id '${name}' is already registered. Please pick a unique identifier for your transforms and/or register them only once. This is to ensure that transforms can be serialized and replayed.`);
@@ -90,6 +95,7 @@ export namespace Transformer {
 
         const t: Transformer<A, B, P> = {
             apply(params, props) { return Transform.create<A, B, P>(t as any, params, props); },
+            namespace,
             id,
             definition
         };
diff --git a/src/mol-state/transformer/controller.ts b/src/mol-state/transformer/controller.ts
deleted file mode 100644
index 4d970bf1e035ee3c5a6d75f8a86a7c1f495e2691..0000000000000000000000000000000000000000
--- a/src/mol-state/transformer/controller.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-// TODO: relactive transformer params controller
\ No newline at end of file
diff --git a/src/mol-state/transformer/manager.ts b/src/mol-state/transformer/manager.ts
deleted file mode 100644
index fc04509557cbe18ba20c67ac0c364ed4807c38dd..0000000000000000000000000000000000000000
--- a/src/mol-state/transformer/manager.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-// TODO: index for registered transformers
\ No newline at end of file
diff --git a/src/mol-state/tree.ts b/src/mol-state/tree.ts
new file mode 100644
index 0000000000000000000000000000000000000000..06e83f0ae4236d22443b8774b249e0498088a528
--- /dev/null
+++ b/src/mol-state/tree.ts
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { Transform } from './tree/transform';
+import { ImmutableTree } from './util/immutable-tree';
+import { Transformer } from './transformer';
+import { StateObject } from './object';
+
+interface StateTree extends ImmutableTree<Transform> { }
+
+namespace StateTree {
+    export interface Transient extends ImmutableTree.Transient<Transform> { }
+
+    function _getRef(t: Transform) { return t.ref; }
+
+    export function create() {
+        return ImmutableTree.create<Transform>(Transform.createRoot('<:root:>'), _getRef);
+    }
+
+    export function updateParams<T extends Transformer = Transformer>(tree: StateTree, ref: Transform.Ref, params: Transformer.Params<T>): StateTree {
+        const t = tree.nodes.get(ref)!.value;
+        const newTransform = Transform.updateParams(t, params);
+        const newTree = ImmutableTree.asTransient(tree);
+        newTree.setValue(ref, newTransform);
+        return newTree.asImmutable();
+    }
+
+    export function toJSON(tree: StateTree) {
+        return ImmutableTree.toJSON(tree, Transform.toJSON);
+    }
+
+    export function fromJSON(data: any): StateTree {
+        return ImmutableTree.fromJSON(data, _getRef, Transform.fromJSON);
+    }
+
+    export interface Builder {
+        getTree(): StateTree
+    }
+
+    export function build(tree: StateTree) {
+        return new Builder.Root(tree);
+    }
+
+    export namespace Builder {
+        interface State {
+            tree: StateTree.Transient
+        }
+
+        export class Root implements Builder {
+            private state: State;
+            to<A extends StateObject>(ref: Transform.Ref) { return new To<A>(this.state, ref); }
+            toRoot<A extends StateObject>() { return new To<A>(this.state, this.state.tree.rootRef as any); }
+            delete(ref: Transform.Ref) { this.state.tree.remove(ref); return this; }
+            getTree(): StateTree { return this.state.tree.asImmutable(); }
+            constructor(tree: StateTree) { this.state = { tree: ImmutableTree.asTransient(tree) } }
+        }
+
+        export class To<A extends StateObject> implements Builder {
+            apply<T extends Transformer<A, any, any>>(tr: T, params?: Transformer.Params<T>, props?: Partial<Transform.Props>): To<Transformer.To<T>> {
+                const t = tr.apply(params, props);
+                this.state.tree.add(this.ref, t);
+                return new To(this.state, t.ref);
+            }
+
+            getTree(): StateTree { return this.state.tree.asImmutable(); }
+
+            constructor(private state: State, private ref: Transform.Ref) {
+                if (!this.state.tree.nodes.has(ref)) {
+                    throw new Error(`Could not find node '${ref}'.`);
+                }
+            }
+        }
+    }
+}
+
+export { StateTree }
\ No newline at end of file
diff --git a/src/mol-state/tree/action.ts b/src/mol-state/tree/action.ts
deleted file mode 100644
index f5216c5abbeb50e7497369b1675c2109cbf4db49..0000000000000000000000000000000000000000
--- a/src/mol-state/tree/action.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-// TODO: tree actions: Add, Update, Delete; action queue
\ No newline at end of file
diff --git a/src/mol-state/tree/builder.ts b/src/mol-state/tree/builder.ts
deleted file mode 100644
index 4ed5632bc555c864c0ca194622bd85e4de4f6228..0000000000000000000000000000000000000000
--- a/src/mol-state/tree/builder.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { ImmutableTree } from '../util/immutable-tree';
-import { TransformTree } from './tree';
-import { StateObject } from '../object';
-import { Transform } from './transform';
-import { Transformer } from '../transformer';
-
-export interface StateTreeBuilder {
-    getTree(): TransformTree
-}
-
-export namespace StateTreeBuilder {
-    interface State {
-        tree: TransformTree.Transient
-    }
-
-    export function create(tree: TransformTree) {
-        return new Root(tree);
-    }
-
-    export class Root implements StateTreeBuilder {
-        private state: State;
-        //to<A extends StateObject>(ref: Transform.Ref) { return new To<A>(this.state, ref); }
-        to<A extends StateObject>(ref: Transform.Ref) { return new To<A>(this.state, ref); }
-        toRoot<A extends StateObject>() { return new To<A>(this.state, this.state.tree.rootRef as any); }
-        getTree(): TransformTree { return this.state.tree.asImmutable(); }
-        constructor(tree: TransformTree) { this.state = { tree: ImmutableTree.asTransient(tree) } }
-    }
-
-    export class To<A extends StateObject> implements StateTreeBuilder {
-        apply<T extends Transformer<A, any, any>>(tr: T, params?: Transformer.Params<T>, props?: Partial<Transform.Props>): To<Transformer.To<T>> {
-            const t = tr.apply(params, props);
-            this.state.tree.add(this.ref, t);
-            return new To(this.state, t.ref);
-        }
-
-        getTree(): TransformTree { return this.state.tree.asImmutable(); }
-
-        constructor(private state: State, private ref: Transform.Ref) {
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-state/tree/context.ts b/src/mol-state/tree/context.ts
deleted file mode 100644
index 1c274d8cc9b04844ecf2c6dbeae524a15a7bcc82..0000000000000000000000000000000000000000
--- a/src/mol-state/tree/context.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { EventDispatcher } from '../event/event';
-
-export interface TransformContext {
-    /** An event dispatcher for executing child tasks. */
-    dispatcher: EventDispatcher,
-
-    globalContext: any
-    // tree: ModelTree
-}
\ No newline at end of file
diff --git a/src/mol-state/tree/selection.ts b/src/mol-state/tree/selection.ts
index 7c7fe83382a744be37fe5118239b71702aebc60d..84130cdc3dfe2d525171ec6063abbfe696bc67cc 100644
--- a/src/mol-state/tree/selection.ts
+++ b/src/mol-state/tree/selection.ts
@@ -4,4 +4,8 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-// TODO
\ No newline at end of file
+namespace StateTreeSelection {
+
+}
+
+export { StateTreeSelection }
\ No newline at end of file
diff --git a/src/mol-state/tree/transform.ts b/src/mol-state/tree/transform.ts
index 7c7af9e93cf2bbc3bc546648a08a5125a0ef6e6e..6e494e9d2309cc4928d258c8b48e3994c2604a08 100644
--- a/src/mol-state/tree/transform.ts
+++ b/src/mol-state/tree/transform.ts
@@ -12,7 +12,8 @@ export interface Transform<A extends StateObject = StateObject, B extends StateO
     readonly transformer: Transformer<A, B, P>,
     readonly params: P,
     readonly ref: Transform.Ref,
-    readonly version: string
+    readonly version: string,
+    readonly defaultProps?: unknown
 }
 
 export namespace Transform {
@@ -49,7 +50,8 @@ export namespace Transform {
         transformer: string,
         params: any,
         ref: string,
-        version: string
+        version: string,
+        defaultProps?: unknown
     }
 
     function _id(x: any) { return x; }
@@ -61,7 +63,8 @@ export namespace Transform {
             transformer: t.transformer.id,
             params: pToJson(t.params),
             ref: t.ref,
-            version: t.version
+            version: t.version,
+            defaultProps: t.defaultProps
         };
     }
 
@@ -74,7 +77,8 @@ export namespace Transform {
             transformer,
             params: pFromJson(t.params),
             ref: t.ref,
-            version: t.version
+            version: t.version,
+            defaultProps: t.defaultProps
         };
     }
 }
\ No newline at end of file
diff --git a/src/mol-state/tree/tree.ts b/src/mol-state/tree/tree.ts
deleted file mode 100644
index 686a0941d23da77f3b6dc9f9225bb534a9dce152..0000000000000000000000000000000000000000
--- a/src/mol-state/tree/tree.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { Transform } from './transform';
-import { ImmutableTree } from '../util/immutable-tree';
-import { Transformer } from '../transformer';
-
-export interface TransformTree extends ImmutableTree<Transform> { }
-
-export namespace TransformTree {
-    export interface Transient extends ImmutableTree.Transient<Transform> { }
-
-    function _getRef(t: Transform) { return t.ref; }
-
-    export function create() {
-        return ImmutableTree.create<Transform>(Transform.createRoot('<:root:>'), _getRef);
-    }
-
-    export function updateParams<T extends Transformer = Transformer>(tree: TransformTree, ref: Transform.Ref, params: Transformer.Params<T>): TransformTree {
-        const t = tree.nodes.get(ref)!.value;
-        const newTransform = Transform.updateParams(t, params);
-        const newTree = ImmutableTree.asTransient(tree);
-        newTree.setValue(ref, newTransform);
-        return newTree.asImmutable();
-    }
-
-    export function toJSON(tree: TransformTree) {
-        return ImmutableTree.toJSON(tree, Transform.toJSON);
-    }
-
-    export function fromJSON(data: any): TransformTree {
-        return ImmutableTree.fromJSON(data, _getRef, Transform.fromJSON);
-    }
-}
\ No newline at end of file
diff --git a/src/mol-state/util/immutable-tree.ts b/src/mol-state/util/immutable-tree.ts
index e4ab973da5e7fcc606aeef1fcec84d66fc975d3b..421f8c3bb9c0f2b53ef239dc2427fae1d3d0f974 100644
--- a/src/mol-state/util/immutable-tree.ts
+++ b/src/mol-state/util/immutable-tree.ts
@@ -62,7 +62,7 @@ export namespace ImmutableTree {
     type VisitorCtx = { nodes: Ns, state: any, f: (node: N, nodes: Ns, state: any) => boolean | undefined | void };
 
     function _postOrderFunc(this: VisitorCtx, c: ImmutableTree.Ref | undefined) { _doPostOrder(this, this.nodes.get(c!)!); }
-    function _doPostOrder<T, S>(ctx: VisitorCtx, root: N) {
+    function _doPostOrder(ctx: VisitorCtx, root: N) {
         if (root.children.size) {
             root.children.forEach(_postOrderFunc, ctx);
         }
@@ -79,7 +79,7 @@ export namespace ImmutableTree {
     }
 
     function _preOrderFunc(this: VisitorCtx, c: ImmutableTree.Ref | undefined) { _doPreOrder(this, this.nodes.get(c!)!); }
-    function _doPreOrder<T, S>(ctx: VisitorCtx, root: N) {
+    function _doPreOrder(ctx: VisitorCtx, root: N) {
         const ret = ctx.f(root, ctx.nodes, ctx.state);
         if (typeof ret === 'boolean' && !ret) return;
         if (root.children.size) {
@@ -225,12 +225,7 @@ export namespace ImmutableTree {
             const parent = nodes.get(node.parent)!;
             const children = mutate(parent.ref).children;
             const st = subtreePostOrder(this, node);
-            if (parent.ref === node.ref) {
-                nodes.clear();
-                mutations.clear();
-                return st;
-            }
-            children.delete(ref);
+            if (ref !== this.rootRef) children.delete(ref);
             for (const n of st) {
                 nodes.delete(n.value.ref);
                 mutations.delete(n.value.ref);
diff --git a/src/mol-util/color/scale.ts b/src/mol-util/color/scale.ts
index 403bf485bec674d3081764df61ddbc7a049f0428..08f3a2c051d34438e605d549d6a9c6d0c5d170ce 100644
--- a/src/mol-util/color/scale.ts
+++ b/src/mol-util/color/scale.ts
@@ -6,7 +6,7 @@
 
 import { Color } from './color'
 import { ColorBrewer } from './tables'
-import { ScaleLegend } from 'mol-view/theme/color';
+import { ScaleLegend } from 'mol-canvas3d/theme/color';
 import { defaults } from 'mol-util';
 
 export interface ColorScale {
diff --git a/src/mol-util/object.ts b/src/mol-util/object.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ee047d59ee226390d30cf68beb09f6f21b7df22
--- /dev/null
+++ b/src/mol-util/object.ts
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+const hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/** Create new object if any property in "update" changes in "source". */
+export function shallowMerge2<T>(source: T, update: Partial<T>): T {
+    // Adapted from LiteMol (https://github.com/dsehnal/LiteMol)
+    let changed = false;
+    for (let k of Object.keys(update)) {
+        if (!hasOwnProperty.call(update, k)) continue;
+
+        if ((update as any)[k] !== (source as any)[k]) {
+            changed = true;
+            break;
+        }
+    }
+
+    if (!changed) return source;
+    return Object.assign({}, source, update);
+}
+
+export function shallowEqual<T>(a: T, b: T) {
+    if (!a) {
+        if (!b) return true;
+        return false;
+    }
+    if (!b) return false;
+
+    let keys = Object.keys(a);
+    if (Object.keys(b).length !== keys.length) return false;
+    for (let k of keys) {
+        if (!hasOwnProperty.call(a, k) || (a as any)[k] !== (b as any)[k]) return false;
+    }
+
+    return true;
+}
+
+export function shallowMerge<T>(source: T, ...rest: (Partial<T> | undefined)[]): T {
+    // Adapted from LiteMol (https://github.com/dsehnal/LiteMol)
+    let ret: any = source;
+
+    for (let s = 0; s < rest.length; s++) {
+        if (!rest[s]) continue;
+        ret = shallowMerge2(source, rest[s] as T);
+        if (ret !== source) {
+            for (let i = s + 1; i < rest.length; i++) {
+                ret = Object.assign(ret, rest[i]);
+            }
+            break;
+        }
+    }
+    return ret;
+}
\ No newline at end of file
diff --git a/src/mol-view/parameter.ts b/src/mol-util/parameter.ts
similarity index 89%
rename from src/mol-view/parameter.ts
rename to src/mol-util/parameter.ts
index 2110b3db36ba6eab84764a4210e1e88e636b4667..5cfe464993cf70ea4bbe3e811d723afbba0d4b7c 100644
--- a/src/mol-view/parameter.ts
+++ b/src/mol-util/parameter.ts
@@ -4,8 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Color } from 'mol-util/color';
-import { Structure } from 'mol-model/structure';
+import { Color } from './color';
 
 export interface BaseParam<T> {
     label: string
@@ -81,15 +80,7 @@ export function NumberParam(label: string, description: string, defaultValue: nu
     return { type: 'number', label, description, defaultValue, min, max, step }
 }
 
-export interface StructureParam extends BaseParam<Structure> {
-    type: 'structure'
-}
-export function StructureParam(label: string, description: string, defaultValue: Structure): StructureParam {
-    return { type: 'structure', label, description, defaultValue }
-}
-
-export type Param = ValueParam<any> | SelectParam<any> | MultiSelectParam<any> | BooleanParam | RangeParam | TextParam | ColorParam | NumberParam | StructureParam
-
+export type Param = ValueParam<any> | SelectParam<any> | MultiSelectParam<any> | BooleanParam | RangeParam | TextParam | ColorParam | NumberParam
 export type Params = { [k: string]: Param }
 
 export function paramDefaultValues<T extends Params>(params: T) {
diff --git a/src/mol-view/state/context.ts b/src/mol-view/state/context.ts
deleted file mode 100644
index 2893a5e37fa78d807888cee2cf4effee7a2efcf6..0000000000000000000000000000000000000000
--- a/src/mol-view/state/context.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { BehaviorSubject } from 'rxjs';
-import { UUID } from 'mol-util'
-import { AnyEntity } from './entity';
-import Viewer from '../viewer';
-import { Progress } from 'mol-task';
-
-// TODO
-export type StateTree = {}
-
-export class StateContext {
-    id = UUID.create()
-    change = new BehaviorSubject(0)
-
-    tree: StateTree = {}
-    entities: Set<AnyEntity> = new Set()
-
-    viewer: Viewer
-
-    constructor(readonly log: (p: Progress) => void) {
-
-    }
-}
diff --git a/src/mol-view/state/entity.ts b/src/mol-view/state/entity.ts
deleted file mode 100644
index 7c16728cbc1fb217b81bf7fdec259bd7c4c94bdf..0000000000000000000000000000000000000000
--- a/src/mol-view/state/entity.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { readFile, readUrl } from 'mol-util/read'
-import { idFactory } from 'mol-util/id-factory'
-import { StateContext } from './context';
-import { getFileInfo } from 'mol-util/file-info';
-import { CifFile, CifFrame } from 'mol-io/reader/cif';
-import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
-import { Model, Structure } from 'mol-model/structure';
-import { StructureRepresentation } from 'mol-geo/representation/structure';
-import { SpacefillProps } from 'mol-geo/representation/structure/representation/spacefill';
-import { BallAndStickProps } from 'mol-geo/representation/structure/representation/ball-and-stick';
-import { DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint';
-import { CartoonProps } from 'mol-geo/representation/structure/representation/cartoon';
-import { BackboneProps } from 'mol-geo/representation/structure/representation/backbone';
-import { CarbohydrateProps } from 'mol-geo/representation/structure/representation/carbohydrate';
-
-const getNextId = idFactory(1)
-
-export interface StateEntity<T, K extends string> {
-    id: number
-    kind: K
-    value: T
-}
-export namespace StateEntity {
-    export function create<T, K extends string>(ctx: StateContext, kind: K, value: T): StateEntity<T, K> {
-        const entity = { id: getNextId(), kind, value }
-        ctx.entities.add(entity)
-        ctx.change.next(ctx.change.getValue() + 1)
-        return entity
-    }
-}
-
-export type AnyEntity = StateEntity<any, any>
-export type NullEntity = StateEntity<null, 'null'>
-
-export const NullEntity: NullEntity = { id: -1, kind: 'null', value: null }
-export const RootEntity: StateEntity<null, 'root'> = { id: 0, kind: 'root', value: null }
-
-export interface UrlProps {
-    url: string
-    name: string
-    type: string
-    getData: () => Promise<string | Uint8Array>
-}
-
-export type UrlEntity = StateEntity<UrlProps, 'url'>
-export namespace UrlEntity {
-    export function ofUrl(ctx: StateContext, url: string, isBinary?: boolean): UrlEntity {
-        const { name, ext: type, compressed, binary } = getFileInfo(url)
-        return StateEntity.create(ctx, 'url', {
-            url, name, type,
-            getData: () => readUrl(url, isBinary || !!compressed || binary)
-        })
-    }
-}
-
-export interface FileProps {
-    name: string
-    type: string
-    getData: () => Promise<string | Uint8Array>
-}
-
-export type FileEntity = StateEntity<FileProps, 'file'>
-export namespace FileEntity {
-    export function ofFile(ctx: StateContext, file: File, isBinary?: boolean): FileEntity {
-        const { name, ext: type, compressed, binary } = getFileInfo(file)
-        return StateEntity.create(ctx, 'file', {
-            name, type,
-            getData: () => readFile(file, isBinary || !!compressed || binary)
-        })
-    }
-}
-
-export interface DataProps {
-    type: string
-    data: string | Uint8Array
-}
-
-export type DataEntity = StateEntity<DataProps, 'data'>
-export namespace DataEntity {
-    export function ofData<T>(ctx: StateContext, data: string | Uint8Array, type: string): DataEntity {
-        return StateEntity.create(ctx, 'data', {
-            type,
-            data
-        })
-    }
-}
-
-export type CifEntity = StateEntity<CifFile, 'cif'>
-export namespace CifEntity {
-    export function ofCifFile(ctx: StateContext, file: CifFile): CifEntity {
-        return StateEntity.create(ctx, 'cif', file)
-    }
-}
-
-export type MmcifEntity = StateEntity<{ db: mmCIF_Database, frame: CifFrame }, 'mmcif'>
-export namespace MmcifEntity {
-    export function ofMmcifDb(ctx: StateContext, mmCif: { db: mmCIF_Database, frame: CifFrame }): MmcifEntity {
-        return StateEntity.create(ctx, 'mmcif', mmCif)
-    }
-}
-
-export type ModelEntity = StateEntity<ReadonlyArray<Model>, 'model'>
-export namespace ModelEntity {
-    export function ofModels(ctx: StateContext, models: ReadonlyArray<Model>): ModelEntity {
-        return StateEntity.create(ctx, 'model', models)
-    }
-}
-
-export type StructureEntity = StateEntity<Structure, 'structure'>
-export namespace StructureEntity {
-    export function ofStructure(ctx: StateContext, structure: Structure): StructureEntity {
-        return StateEntity.create(ctx, 'structure', structure)
-    }
-}
-
-export type SpacefillEntity = StateEntity<StructureRepresentation<SpacefillProps>, 'spacefill'>
-export namespace SpacefillEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<SpacefillProps>): SpacefillEntity {
-        return StateEntity.create(ctx, 'spacefill', repr)
-    }
-}
-
-export type BallAndStickEntity = StateEntity<StructureRepresentation<BallAndStickProps>, 'ballandstick'>
-export namespace BallAndStickEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<BallAndStickProps>): BallAndStickEntity {
-        return StateEntity.create(ctx, 'ballandstick', repr)
-    }
-}
-
-export type DistanceRestraintEntity = StateEntity<StructureRepresentation<DistanceRestraintProps>, 'distancerestraint'>
-export namespace DistanceRestraintEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<DistanceRestraintProps>): DistanceRestraintEntity {
-        return StateEntity.create(ctx, 'distancerestraint', repr)
-    }
-}
-
-export type BackboneEntity = StateEntity<StructureRepresentation<BackboneProps>, 'backbone'>
-export namespace BackboneEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<BackboneProps>): BackboneEntity {
-        return StateEntity.create(ctx, 'backbone', repr)
-    }
-}
-
-export type CartoonEntity = StateEntity<StructureRepresentation<CartoonProps>, 'cartoon'>
-export namespace CartoonEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<CartoonProps>): CartoonEntity {
-        return StateEntity.create(ctx, 'cartoon', repr)
-    }
-}
-
-export type CarbohydrateEntity = StateEntity<StructureRepresentation<CarbohydrateProps>, 'carbohydrate'>
-export namespace CarbohydrateEntity {
-    export function ofRepr(ctx: StateContext, repr: StructureRepresentation<CarbohydrateProps>): CarbohydrateEntity {
-        return StateEntity.create(ctx, 'carbohydrate', repr)
-    }
-}
\ No newline at end of file
diff --git a/src/mol-view/state/transform.ts b/src/mol-view/state/transform.ts
deleted file mode 100644
index bb454c3c5d7711e2869a085e253fb52c769f2074..0000000000000000000000000000000000000000
--- a/src/mol-view/state/transform.ts
+++ /dev/null
@@ -1,274 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import CIF from 'mol-io/reader/cif'
-import { FileEntity, DataEntity, UrlEntity, CifEntity, MmcifEntity, ModelEntity, StructureEntity, SpacefillEntity, AnyEntity, NullEntity, BallAndStickEntity, DistanceRestraintEntity, CartoonEntity, BackboneEntity, CarbohydrateEntity } from './entity';
-import { Model, Structure, Format } from 'mol-model/structure';
-
-import { StateContext } from './context';
-import StructureSymmetry from 'mol-model/structure/structure/symmetry';
-import { SpacefillProps, SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill';
-import { BallAndStickProps, BallAndStickRepresentation } from 'mol-geo/representation/structure/representation/ball-and-stick';
-import { DistanceRestraintRepresentation, DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint';
-import { CartoonRepresentation, CartoonProps } from 'mol-geo/representation/structure/representation/cartoon';
-import { BackboneProps, BackboneRepresentation } from 'mol-geo/representation/structure/representation/backbone';
-import { CarbohydrateProps, CarbohydrateRepresentation } from 'mol-geo/representation/structure/representation/carbohydrate';
-
-type transformer<I extends AnyEntity, O extends AnyEntity, P extends {}> = (ctx: StateContext, inputEntity: I, props?: P) => Promise<O>
-
-export interface StateTransform<I extends AnyEntity, O extends AnyEntity, P extends {}> {
-    inputKind: I['kind']
-    outputKind: O['kind']
-    kind: string
-    apply: transformer<I, O, P>
-}
-
-export namespace StateTransform {
-    export function create<I extends AnyEntity, O extends AnyEntity, P extends {}>(inputKind: I['kind'], outputKind: O['kind'], kind: string, transformer: transformer<I, O, P>) {
-        return { inputKind, outputKind, kind, apply: transformer }
-    }
-}
-
-export type AnyTransform = StateTransform<AnyEntity, AnyEntity, {}>
-
-export type UrlToData = StateTransform<UrlEntity, DataEntity, {}>
-export const UrlToData: UrlToData = StateTransform.create('url', 'data', 'url-to-data',
-    async function (ctx: StateContext, urlEntity: UrlEntity) {
-        return DataEntity.ofData(ctx, await urlEntity.value.getData(), urlEntity.value.type)
-    })
-
-export type FileToData = StateTransform<FileEntity, DataEntity, {}>
-export const FileToData: FileToData = StateTransform.create('file', 'data', 'file-to-data',
-    async function (ctx: StateContext, fileEntity: FileEntity) {
-        return DataEntity.ofData(ctx, await fileEntity.value.getData(), fileEntity.value.type)
-    })
-
-export type DataToCif = StateTransform<DataEntity, CifEntity, {}>
-export const DataToCif: DataToCif = StateTransform.create('data', 'cif', 'data-to-cif',
-    async function (ctx: StateContext, dataEntity: DataEntity) {
-        const comp = CIF.parse(dataEntity.value.data)
-        const parsed = await comp.run(ctx.log)
-        if (parsed.isError) throw parsed
-        return CifEntity.ofCifFile(ctx, parsed.result)
-    })
-
-export type CifToMmcif = StateTransform<CifEntity, MmcifEntity, {}>
-export const CifToMmcif: CifToMmcif = StateTransform.create('cif', 'mmcif', 'cif-to-mmcif',
-    async function (ctx: StateContext, cifEntity: CifEntity) {
-        const frame = cifEntity.value.blocks[0];
-        return MmcifEntity.ofMmcifDb(ctx, { frame, db: CIF.schema.mmCIF(frame) })
-    })
-
-export type MmcifToModel = StateTransform<MmcifEntity, ModelEntity, {}>
-export const MmcifToModel: MmcifToModel = StateTransform.create('mmcif', 'model', 'mmcif-to-model',
-    async function (ctx: StateContext, mmcifEntity: MmcifEntity) {
-        const models = await Model.create(Format.mmCIF(mmcifEntity.value.frame, mmcifEntity.value.db)).run(ctx.log)
-        return ModelEntity.ofModels(ctx, models)
-    })
-
-export interface StructureProps {
-    assembly?: string
-}
-
-export type ModelToStructure = StateTransform<ModelEntity, StructureEntity, StructureProps>
-export const ModelToStructure: ModelToStructure = StateTransform.create('model', 'structure', 'model-to-structure',
-    async function (ctx: StateContext, modelEntity: ModelEntity, props: StructureProps = {}) {
-        const model = modelEntity.value[0]
-        const assembly = props.assembly
-        let structure: Structure
-        const assemblies = model.symmetry.assemblies
-        if (assemblies.length) {
-            structure = await StructureSymmetry.buildAssembly(Structure.ofModel(model), assembly || '1').run(ctx.log)
-        } else {
-            structure = Structure.ofModel(model)
-        }
-        return StructureEntity.ofStructure(ctx, structure)
-    })
-
-export type StructureCenter = StateTransform<StructureEntity, NullEntity, {}>
-export const StructureCenter: StructureCenter = StateTransform.create('structure', 'null', 'structure-center',
-    async function (ctx: StateContext, structureEntity: StructureEntity) {
-        ctx.viewer.center(structureEntity.value.boundary.sphere.center)
-        return NullEntity
-    })
-
-export type StructureToSpacefill = StateTransform<StructureEntity, SpacefillEntity, Partial<SpacefillProps>>
-export const StructureToSpacefill: StructureToSpacefill = StateTransform.create('structure', 'spacefill', 'structure-to-spacefill',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<SpacefillProps> = {}) {
-        const spacefillRepr = SpacefillRepresentation()
-        await spacefillRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(spacefillRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return SpacefillEntity.ofRepr(ctx, spacefillRepr)
-    })
-
-export type StructureToBallAndStick = StateTransform<StructureEntity, BallAndStickEntity, Partial<BallAndStickProps>>
-export const StructureToBallAndStick: StructureToBallAndStick = StateTransform.create('structure', 'ballandstick', 'structure-to-ballandstick',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<BallAndStickProps> = {}) {
-        const ballAndStickRepr = BallAndStickRepresentation()
-        await ballAndStickRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(ballAndStickRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return BallAndStickEntity.ofRepr(ctx, ballAndStickRepr)
-    })
-
-export type StructureToDistanceRestraint = StateTransform<StructureEntity, DistanceRestraintEntity, Partial<DistanceRestraintProps>>
-export const StructureToDistanceRestraint: StructureToDistanceRestraint = StateTransform.create('structure', 'distancerestraint', 'structure-to-distancerestraint',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<DistanceRestraintProps> = {}) {
-        const distanceRestraintRepr = DistanceRestraintRepresentation()
-        await distanceRestraintRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(distanceRestraintRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return DistanceRestraintEntity.ofRepr(ctx, distanceRestraintRepr)
-    })
-
-export type StructureToBackbone = StateTransform<StructureEntity, BackboneEntity, Partial<BackboneProps>>
-export const StructureToBackbone: StructureToBackbone = StateTransform.create('structure', 'backbone', 'structure-to-backbone',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<BackboneProps> = {}) {
-        const backboneRepr = BackboneRepresentation()
-        await backboneRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(backboneRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return BackboneEntity.ofRepr(ctx, backboneRepr)
-    })
-
-export type StructureToCartoon = StateTransform<StructureEntity, CartoonEntity, Partial<CartoonProps>>
-export const StructureToCartoon: StructureToCartoon = StateTransform.create('structure', 'cartoon', 'structure-to-cartoon',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<CartoonProps> = {}) {
-        const cartoonRepr = CartoonRepresentation()
-        await cartoonRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(cartoonRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return CartoonEntity.ofRepr(ctx, cartoonRepr)
-    })
-
-export type StructureToCarbohydrate = StateTransform<StructureEntity, CarbohydrateEntity, Partial<CarbohydrateProps>>
-export const StructureToCarbohydrate: StructureToCarbohydrate = StateTransform.create('structure', 'carbohydrate', 'structure-to-cartoon',
-    async function (ctx: StateContext, structureEntity: StructureEntity, props: Partial<CarbohydrateProps> = {}) {
-        const carbohydrateRepr = CarbohydrateRepresentation()
-        await carbohydrateRepr.createOrUpdate(props, structureEntity.value).run(ctx.log)
-        ctx.viewer.add(carbohydrateRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return CarbohydrateEntity.ofRepr(ctx, carbohydrateRepr)
-    })
-
-export type SpacefillUpdate = StateTransform<SpacefillEntity, NullEntity, Partial<SpacefillProps>>
-export const SpacefillUpdate: SpacefillUpdate = StateTransform.create('spacefill', 'null', 'spacefill-update',
-    async function (ctx: StateContext, spacefillEntity: SpacefillEntity, props: Partial<SpacefillProps> = {}) {
-        const spacefillRepr = spacefillEntity.value
-        await spacefillRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(spacefillRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-export type BallAndStickUpdate = StateTransform<BallAndStickEntity, NullEntity, Partial<BallAndStickProps>>
-export const BallAndStickUpdate: BallAndStickUpdate = StateTransform.create('ballandstick', 'null', 'ballandstick-update',
-    async function (ctx: StateContext, ballAndStickEntity: BallAndStickEntity, props: Partial<BallAndStickProps> = {}) {
-        const ballAndStickRepr = ballAndStickEntity.value
-        await ballAndStickRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(ballAndStickRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-export type DistanceRestraintUpdate = StateTransform<DistanceRestraintEntity, NullEntity, Partial<DistanceRestraintProps>>
-export const DistanceRestraintUpdate: DistanceRestraintUpdate = StateTransform.create('distancerestraint', 'null', 'distancerestraint-update',
-    async function (ctx: StateContext, distanceRestraintEntity: DistanceRestraintEntity, props: Partial<DistanceRestraintProps> = {}) {
-        const distanceRestraintRepr = distanceRestraintEntity.value
-        await distanceRestraintRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(distanceRestraintRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-export type BackboneUpdate = StateTransform<BackboneEntity, NullEntity, Partial<BackboneProps>>
-export const BackboneUpdate: BackboneUpdate = StateTransform.create('backbone', 'null', 'backbone-update',
-    async function (ctx: StateContext, backboneEntity: BackboneEntity, props: Partial<BackboneProps> = {}) {
-        const backboneRepr = backboneEntity.value
-        await backboneRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(backboneRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-export type CartoonUpdate = StateTransform<CartoonEntity, NullEntity, Partial<CartoonProps>>
-export const CartoonUpdate: CartoonUpdate = StateTransform.create('cartoon', 'null', 'cartoon-update',
-    async function (ctx: StateContext, cartoonEntity: CartoonEntity, props: Partial<CartoonProps> = {}) {
-        const cartoonRepr = cartoonEntity.value
-        await cartoonRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(cartoonRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-export type CarbohydrateUpdate = StateTransform<CarbohydrateEntity, NullEntity, Partial<CarbohydrateProps>>
-export const CarbohydrateUpdate: CarbohydrateUpdate = StateTransform.create('carbohydrate', 'null', 'carbohydrate-update',
-    async function (ctx: StateContext, carbohydrateEntity: CarbohydrateEntity, props: Partial<CarbohydrateProps> = {}) {
-        const carbohydrateRepr = carbohydrateEntity.value
-        await carbohydrateRepr.createOrUpdate(props).run(ctx.log)
-        ctx.viewer.add(carbohydrateRepr)
-        ctx.viewer.requestDraw()
-        console.log('stats', ctx.viewer.stats)
-        return NullEntity
-    })
-
-// composed
-
-export type MmcifUrlToModel = StateTransform<UrlEntity, ModelEntity, {}>
-export const MmcifUrlToModel: MmcifUrlToModel = StateTransform.create('url', 'model', 'url-to-model',
-    async function (ctx: StateContext, urlEntity: UrlEntity) {
-        const dataEntity = await UrlToData.apply(ctx, urlEntity)
-        return DataToModel.apply(ctx, dataEntity)
-    })
-
-export type MmcifFileToModel = StateTransform<FileEntity, ModelEntity, {}>
-export const MmcifFileToModel: MmcifFileToModel = StateTransform.create('file', 'model', 'file-to-model',
-    async function (ctx: StateContext, fileEntity: FileEntity) {
-        const dataEntity = await FileToData.apply(ctx, fileEntity)
-        return DataToModel.apply(ctx, dataEntity)
-    })
-
-export type DataToModel = StateTransform<DataEntity, ModelEntity, {}>
-export const DataToModel: DataToModel = StateTransform.create('data', 'model', 'data-to-model',
-    async function getModelFromData(ctx: StateContext, dataEntity: DataEntity) {
-        const cifEntity = await DataToCif.apply(ctx, dataEntity)
-        const mmcifEntity = await CifToMmcif.apply(ctx, cifEntity)
-        return MmcifToModel.apply(ctx, mmcifEntity)
-    })
-
-export type ModelToSpacefill = StateTransform<ModelEntity, SpacefillEntity, Partial<SpacefillProps>>
-export const ModelToSpacefill: ModelToSpacefill = StateTransform.create('model', 'spacefill', 'model-to-spacefill',
-    async function (ctx: StateContext, modelEntity: ModelEntity, props: Partial<SpacefillProps> = {}) {
-        const structureEntity = await ModelToStructure.apply(ctx, modelEntity)
-        // StructureToBond.apply(ctx, structureEntity, props)
-        return StructureToSpacefill.apply(ctx, structureEntity, props)
-    })
-
-export type MmcifUrlToSpacefill = StateTransform<UrlEntity, SpacefillEntity, Partial<SpacefillProps>>
-export const MmcifUrlToSpacefill: MmcifUrlToSpacefill = StateTransform.create('url', 'spacefill', 'url-to-spacefill',
-    async function (ctx: StateContext, urlEntity: UrlEntity, props: Partial<SpacefillProps> = {}) {
-        const modelEntity = await MmcifUrlToModel.apply(ctx, urlEntity)
-        return ModelToSpacefill.apply(ctx, modelEntity, props)
-    })
-
-export type MmcifFileToSpacefill = StateTransform<FileEntity, SpacefillEntity, Partial<SpacefillProps>>
-export const MmcifFileToSpacefill: MmcifFileToSpacefill = StateTransform.create('file', 'spacefill', 'file-to-spacefill',
-    async function (ctx: StateContext, fileEntity: FileEntity, props: Partial<SpacefillProps> = {}) {
-        const modelEntity = await MmcifFileToModel.apply(ctx, fileEntity)
-        return ModelToSpacefill.apply(ctx, modelEntity, props)
-    })
\ No newline at end of file
diff --git a/src/mol-view/util.ts b/src/mol-view/util.ts
deleted file mode 100644
index 0fa3e82b42a181d4d3dd9f77aabce3007c2c87b8..0000000000000000000000000000000000000000
--- a/src/mol-view/util.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import CIF from 'mol-io/reader/cif'
-import { Progress } from 'mol-task'
-import { VolumeData, parseDensityServerData } from 'mol-model/volume'
-import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server';
-
-export async function downloadCif(url: string, isBinary: boolean) {
-    const data = await fetch(url);
-    return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
-}
-
-export async function parseCif(data: string|Uint8Array) {
-    const comp = CIF.parse(data)
-    const parsed = await comp.run(Progress.format);
-    if (parsed.isError) throw parsed;
-    return parsed.result
-}
-
-export type Volume = { source: DensityServer_Data_Database, volume: VolumeData }
-
-export async function getVolumeFromEmdId(emdid: string): Promise<Volume> {
-    const cif = await downloadCif(`https://webchem.ncbr.muni.cz/DensityServer/em/emd-${emdid}/cell?detail=4`, true)
-    const data = CIF.schema.densityServer(cif.blocks[1])
-    return { source: data, volume: await parseDensityServerData(data).run() }
-}
-
-export function resizeCanvas (canvas: HTMLCanvasElement, container: Element) {
-    let w = window.innerWidth
-    let h = window.innerHeight
-    if (container !== document.body) {
-        let bounds = container.getBoundingClientRect()
-        w = bounds.right - bounds.left
-        h = bounds.bottom - bounds.top
-    }
-    canvas.width = window.devicePixelRatio * w
-    canvas.height = window.devicePixelRatio * h
-    Object.assign(canvas.style, { width: `${w}px`, height: `${h}px` })
-}
\ No newline at end of file
diff --git a/src/perf-tests/state.ts b/src/perf-tests/state.ts
index af121c96d5a6e48b508872bf141e8e7495be1188..0344b8dc4ff318ab8c32d9cba4d381f06407f31f 100644
--- a/src/perf-tests/state.ts
+++ b/src/perf-tests/state.ts
@@ -1,10 +1,6 @@
-import { Transformer } from 'mol-state/transformer';
-import { StateObject } from 'mol-state/object';
+import { State, StateObject, StateTree, Transformer } from 'mol-state';
 import { Task } from 'mol-task';
-import { TransformTree } from 'mol-state/tree/tree';
-import { StateTreeBuilder } from 'mol-state/tree/builder';
-import { State } from 'mol-state/state';
-import * as util from 'util'
+import * as util from 'util';
 
 export type TypeClass = 'root' | 'shape' | 'prop'
 export interface ObjProps { label: string }
@@ -18,19 +14,17 @@ export class Square extends _obj<{ a: number }>('square', { name: 'Square', clas
 export class Circle extends _obj<{ r: number }>('circle', { name: 'Circle', class: 'shape' }) { }
 export class Area extends _obj<{ volume: number }>('volume', { name: 'Volume', class: 'prop' }) { }
 
-const root = new Root({ label: 'Root' }, {});
-
 export const CreateSquare = _transform<Root, Square, { a: number }>({
     name: 'create-square',
     from: [Root],
     to: [Square],
-    apply(a, p) {
+    apply({ params: p }) {
         return new Square({ label: `Square a=${p.a}` }, p);
     },
-    update(a, _, b, p) {
+    update({ b, newParams: p }) {
         b.props.label = `Square a=${p.a}`
         b.data.a = p.a;
-        return b;
+        return Transformer.UpdateResult.Updated;
     }
 });
 
@@ -38,13 +32,13 @@ export const CreateCircle = _transform<Root, Circle, { r: number }>({
     name: 'create-circle',
     from: [Root],
     to: [Square],
-    apply(a, p) {
+    apply({ params: p }) {
         return new Circle({ label: `Circle r=${p.r}` }, p);
     },
-    update(a, _, b, p) {
+    update({ b, newParams: p }) {
         b.props.label = `Circle r=${p.r}`
         b.data.r = p.r;
-        return b;
+        return Transformer.UpdateResult.Updated;
     }
 });
 
@@ -52,35 +46,39 @@ export const CaclArea = _transform<Square | Circle, Area, {}>({
     name: 'calc-area',
     from: [Square, Circle],
     to: [Area],
-    apply(a) {
+    apply({ a }) {
         if (a instanceof Square) return new Area({ label: 'Area' }, { volume: a.data.a * a.data.a });
         else if (a instanceof Circle) return new Area({ label: 'Area' }, { volume: a.data.r * a.data.r * Math.PI });
         throw new Error('Unknown object type.');
     },
-    update(a, _, b) {
+    update({ a, b }) {
         if (a instanceof Square) b.data.volume = a.data.a * a.data.a;
         else if (a instanceof Circle) b.data.volume = a.data.r * a.data.r * Math.PI;
         else throw new Error('Unknown object type.');
-        return b;
+        return Transformer.UpdateResult.Updated;
     }
 });
 
-async function runTask<A>(t: A | Task<A>): Promise<A> {
+export async function runTask<A>(t: A | Task<A>): Promise<A> {
     if ((t as any).run) return await (t as Task<A>).run();
     return t as A;
 }
 
-export async function test() {
-    const sq = await runTask(CreateSquare.definition.apply(root, { a: 10 }, 0 as any));
-    const area = await runTask(CaclArea.definition.apply(sq, {}, 0 as any));
-    console.log(area);
+function hookEvents(state: State) {
+    state.context.events.object.created.subscribe(e => console.log('created:', e.ref));
+    state.context.events.object.removed.subscribe(e => console.log('removed:', e.ref));
+    state.context.events.object.replaced.subscribe(e => console.log('replaced:', e.ref));
+    state.context.events.object.stateChanged.subscribe(e => console.log('stateChanged:', e.ref,
+        StateObject.StateType[state.objects.get(e.ref)!.state]));
+    state.context.events.object.updated.subscribe(e => console.log('updated:', e.ref));
 }
 
 export async function testState() {
     const state = State.create();
+    hookEvents(state);
 
-    const tree = state.definition.tree;
-    const builder = StateTreeBuilder.create(tree)
+    const tree = state.tree;
+    const builder = StateTree.build(tree);
     builder.toRoot<Root>()
         .apply(CreateSquare, { a: 10 }, { ref: 'square' })
         .apply(CaclArea);
@@ -88,24 +86,24 @@ export async function testState() {
 
     printTTree(tree1);
 
-    const tree2 = TransformTree.updateParams<typeof CreateSquare>(tree1, 'square', { a: 15 });
+    const tree2 = StateTree.updateParams<typeof CreateSquare>(tree1, 'square', { a: 15 });
     printTTree(tree1);
     printTTree(tree2);
 
-    const state1 = await State.update(state, tree1);
+    const state1 = await State.update(state, tree1).run();
     console.log('----------------');
     console.log(util.inspect(state1.objects, true, 3, true));
 
     console.log('----------------');
-    const jsonString = JSON.stringify(TransformTree.toJSON(tree2), null, 2);
+    const jsonString = JSON.stringify(StateTree.toJSON(tree2), null, 2);
     const jsonData = JSON.parse(jsonString);
     printTTree(tree2);
     console.log(jsonString);
-    const treeFromJson = TransformTree.fromJSON(jsonData);
+    const treeFromJson = StateTree.fromJSON(jsonData);
     printTTree(treeFromJson);
 
     console.log('----------------');
-    const state2 = await State.update(state1, treeFromJson);
+    const state2 = await State.update(state1, treeFromJson).run();
     console.log(util.inspect(state2.objects, true, 3, true));
 }
 
@@ -114,11 +112,11 @@ testState();
 
 //test();
 
-export function printTTree(tree: TransformTree) {
+export function printTTree(tree: StateTree) {
     let lines: string[] = [];
     function print(offset: string, ref: any) {
-        let t = tree.nodes.get(ref)!;
-        let tr = t.value;
+        const t = tree.nodes.get(ref)!;
+        const tr = t.value;
 
         const name = tr.transformer.id;
         lines.push(`${offset}|_ (${ref}) ${name} ${tr.params ? JSON.stringify(tr.params) : ''}, v${t.value.version}`);
diff --git a/tsconfig.json b/tsconfig.json
index aa0ec9bccf5a879ebbe430882ff53c45c66993dd..7b896a74eaf963fef9b0a06b79771c41cc101c97 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -25,9 +25,10 @@
             "mol-ql": ["./mol-ql"],
             "mol-script": ["./mol-script"],
             "mol-state": ["./mol-state", "./mol-state/index.ts"],
+            "mol-plugin": ["./mol-plugin", "./mol-plugin/index.ts"],
             "mol-task": ["./mol-task", "./mol-task/index.ts"],
             "mol-util": ["./mol-util", "./mol-util/index.ts"],
-            "mol-view": ["./mol-view"]
+            "mol-canvas3d": ["./mol-view"]
         }
     },
     "include": [ "**/*" ],