diff --git a/README.md b/README.md
index 888aafbe96f2f40f68004d110642eaf7de32a811..4a7966fc35b4431ba72406d172a4f47042a2a2c7 100644
--- a/README.md
+++ b/README.md
@@ -19,9 +19,10 @@ The core of Mol* currently consists of these modules:
 - `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-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-geo` Creating (molecular) geometries.
 - `mol-theme` Molecular representation themeing.
-- `mol-gl` A lightweight wrapper around WebGL.
+- `mol-repr` Molecular representations.
+- `mol-gl` A 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.
diff --git a/package.json b/package.json
index c3d686a95f3b090aab06a8db8d32c98b2cb37e2f..2a8e33f0618a18dee2d3a64009f085d4f5e82f8b 100644
--- a/package.json
+++ b/package.json
@@ -52,17 +52,18 @@
       "mol-app($|/.*)": "<rootDir>/src/mol-app$1",
       "mol-data($|/.*)": "<rootDir>/src/mol-data$1",
       "mol-geo($|/.*)": "<rootDir>/src/mol-geo$1",
-      "mol-theme($|/.*)": "<rootDir>/src/mol-theme$1",
       "mol-gl($|/.*)": "<rootDir>/src/mol-gl$1",
       "mol-io($|/.*)": "<rootDir>/src/mol-io$1",
       "mol-math($|/.*)": "<rootDir>/src/mol-math$1",
       "mol-model($|/.*)": "<rootDir>/src/mol-model$1",
       "mol-model-props($|/.*)": "<rootDir>/src/mol-model-props$1",
+      "mol-plugin($|/.*)": "<rootDir>/src/mol-plugin$1",
       "mol-ql($|/.*)": "<rootDir>/src/mol-ql$1",
+      "mol-repr($|/.*)": "<rootDir>/src/mol-repr$1",
       "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-task($|/.*)": "<rootDir>/src/mol-task$1",
+      "mol-theme($|/.*)": "<rootDir>/src/mol-theme$1",
       "mol-util($|/.*)": "<rootDir>/src/mol-util$1",
       "mol-canvas3d($|/.*)": "<rootDir>/src/mol-canvas3d$1"
     },
diff --git a/src/apps/canvas/component/representation.tsx b/src/apps/canvas/component/representation.tsx
index cca0ca103bb3e0c91eec71aea8445e02073e2bd9..02fcdea19363ea0b39cc1db364d986908efd46a0 100644
--- a/src/apps/canvas/component/representation.tsx
+++ b/src/apps/canvas/component/representation.tsx
@@ -8,7 +8,7 @@ import * as React from 'react'
 import Canvas3D from 'mol-canvas3d/canvas3d';
 import { App } from '../app';
 import { Params } from 'mol-util/parameter';
-import { Representation } from 'mol-geo/representation';
+import { Representation } from 'mol-repr';
 import { ParametersComponent } from 'mol-app/component/parameters';
 import { ColorTheme } from 'mol-theme/color';
 import { getColorThemeProps } from 'mol-geo/geometry/color-data';
diff --git a/src/apps/canvas/component/structure-view.tsx b/src/apps/canvas/component/structure-view.tsx
index d987ec1fe9e5a0839d243c4855bc03253b06ef9b..9b8fd7d785b34911588028d951b22b6224668994 100644
--- a/src/apps/canvas/component/structure-view.tsx
+++ b/src/apps/canvas/component/structure-view.tsx
@@ -6,9 +6,9 @@
 
 import * as React from 'react'
 import { StructureView } from '../structure-view';
-import { StructureRepresentation } from 'mol-geo/representation/structure';
 import { RepresentationComponent } from './representation';
-import { Representation } from 'mol-geo/representation';
+import { Representation } from 'mol-repr';
+import { StructureRepresentation } from 'mol-repr/structure/index';
 
 export interface StructureViewComponentProps {
     structureView: StructureView
diff --git a/src/apps/canvas/component/volume-view.tsx b/src/apps/canvas/component/volume-view.tsx
index d7b596500b82a4b8f2465b7f313acf950dcf0502..159a0d2176dc108377d34cfa1147038d75bbb852 100644
--- a/src/apps/canvas/component/volume-view.tsx
+++ b/src/apps/canvas/component/volume-view.tsx
@@ -6,9 +6,9 @@
 
 import * as React from 'react'
 import { RepresentationComponent } from './representation';
-import { Representation } from 'mol-geo/representation';
+import { Representation } from 'mol-repr';
 import { VolumeView } from '../volume-view';
-import { VolumeRepresentation } from 'mol-geo/representation/volume';
+import { VolumeRepresentation } from 'mol-repr/volume/index';
 
 export interface VolumeViewComponentProps {
     volumeView: VolumeView
diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts
index 6d2313897c0aa3e7dbc00f2c6257848083295541..80bcac4134052e676c5ef77439c9131291fdb244 100644
--- a/src/apps/canvas/structure-view.ts
+++ b/src/apps/canvas/structure-view.ts
@@ -5,27 +5,27 @@
  */
 
 import { Model, Structure } from 'mol-model/structure';
-import { CartoonRepresentation } from 'mol-geo/representation/structure/representation/cartoon';
-import { BallAndStickRepresentation } from 'mol-geo/representation/structure/representation/ball-and-stick';
 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 Canvas3D from 'mol-canvas3d/canvas3d';
-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';
 // import { Shape } from 'mol-model/shape';
 // import { Color } from 'mol-util/color';
 // import { computeUnitBoundary } from 'mol-model/structure/structure/util/boundary';
 // import { addBoundingBox } from 'mol-geo/mesh/builder/bounding-box';
-import { PointRepresentation } from 'mol-geo/representation/structure/representation/point';
-import { StructureRepresentation } from 'mol-geo/representation/structure';
 import { BehaviorSubject } from 'rxjs';
-import { SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill';
-import { DistanceRestraintRepresentation } from 'mol-geo/representation/structure/representation/distance-restraint';
-import { MolecularSurfaceRepresentation } from 'mol-geo/representation/structure/representation/molecular-surface';
 import { App } from './app';
+import { StructureRepresentation } from 'mol-repr/structure/index';
+import { ShapeRepresentation, ShapeProps } from 'mol-repr/shape/index';
+import { CartoonRepresentation } from 'mol-repr/structure/representation/cartoon';
+import { MolecularSurfaceRepresentation } from 'mol-repr/structure/representation/molecular-surface';
+import { PointRepresentation } from 'mol-repr/structure/representation/point';
+import { BallAndStickRepresentation } from 'mol-repr/structure/representation/ball-and-stick';
+import { CarbohydrateRepresentation } from 'mol-repr/structure/representation/carbohydrate';
+import { SpacefillRepresentation } from 'mol-repr/structure/representation/spacefill';
+import { DistanceRestraintRepresentation } from 'mol-repr/structure/representation/distance-restraint';
 
 export interface StructureView {
     readonly app: App
diff --git a/src/apps/canvas/volume-view.ts b/src/apps/canvas/volume-view.ts
index 0f17a5c9db43bf3019b4946365e97eedd04a967b..bfe46d0e444d3047eea21886908b1d1b7ffba373 100644
--- a/src/apps/canvas/volume-view.ts
+++ b/src/apps/canvas/volume-view.ts
@@ -8,9 +8,9 @@ import Canvas3D from 'mol-canvas3d/canvas3d';
 import { BehaviorSubject } from 'rxjs';
 import { App } from './app';
 import { VolumeData } from 'mol-model/volume';
-import { VolumeRepresentation } from 'mol-geo/representation/volume';
-import { IsosurfaceRepresentation } from 'mol-geo/representation/volume/isosurface-mesh';
-import { DirectVolumeRepresentation } from 'mol-geo/representation/volume/direct-volume';
+import { VolumeRepresentation } from 'mol-repr/volume/index';
+import { IsosurfaceRepresentation } from 'mol-repr/volume/isosurface-mesh';
+import { DirectVolumeRepresentation } from 'mol-repr/volume/direct-volume';
 
 export interface VolumeView {
     readonly app: App
diff --git a/src/apps/structure-info/volume.ts b/src/apps/structure-info/volume.ts
index 790d4f8a91979cdb2767550ee4ad6c4f264b2946..3b7d8cc3f184d882b534f7c38417a8abfb91e6f0 100644
--- a/src/apps/structure-info/volume.ts
+++ b/src/apps/structure-info/volume.ts
@@ -13,9 +13,9 @@ import { downloadCif } from './helpers'
 import CIF from 'mol-io/reader/cif'
 import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server';
 import { Table } from 'mol-data/db';
-import { createVolumeSurface } from 'mol-geo/representation/volume/isosurface-mesh';
 import { StringBuilder } from 'mol-util';
 import { Task } from 'mol-task';
+import { createVolumeIsosurface } from 'mol-repr/volume/isosurface-mesh';
 
 require('util.promisify').shim();
 const writeFileAsync = util.promisify(fs.writeFile);
@@ -38,7 +38,7 @@ function print(data: Volume) {
 }
 
 async function doMesh(data: Volume, filename: string) {
-    const mesh = await Task.create('', ctx => createVolumeSurface(ctx, data.volume, VolumeIsoValue.calcAbsolute(data.volume.dataStats, 1.5))).run();
+    const mesh = await Task.create('', ctx => createVolumeIsosurface(ctx, data.volume, { isoValueAbsolute: VolumeIsoValue.calcAbsolute(data.volume.dataStats, 1.5) } )).run();
     console.log({ vc: mesh.vertexCount, tc: mesh.triangleCount });
 
     // Export the mesh in OBJ format.
diff --git a/src/mol-canvas3d/camera/combined.ts b/src/mol-canvas3d/camera/combined.ts
index 5432afa9b7b614eb49c0b061947a02657f5a1057..e0b1ed41c934f312cf2e9373c1d1ccd72f701f68 100644
--- a/src/mol-canvas3d/camera/combined.ts
+++ b/src/mol-canvas3d/camera/combined.ts
@@ -9,14 +9,6 @@ import { OrthographicCamera } from './orthographic';
 import { Camera, DefaultCameraProps } from './base';
 import { Vec3 } from 'mol-math/linear-algebra';
 
-// TODO
-
-// updateZoom () {
-//     const fov = degToRad(this.perspectiveCamera.fov)
-//     const height = 2 * Math.tan(fov / 2) * -this.camera.position.z
-//     this.orthographicCamera.zoom = this.height / height
-// }
-
 export type CombinedCameraMode = 'perspective' | 'orthographic'
 
 export interface CombinedCamera extends Camera {
@@ -45,11 +37,7 @@ export namespace CombinedCamera {
         return camera
     }
 
-    // const center = Vec3.zero()
     export function update(camera: CombinedCamera) {
-        // console.log(camera.position, camera.direction)
-        // Vec3.add(center, camera.position, camera.direction)
-
         const height = 2 * Math.tan(camera.fov / 2) * Vec3.distance(camera.position, camera.target)
         camera.zoom = camera.viewport.height / height
 
diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts
index 78befa72d895ba5a282d520e458bba73d803863c..0d21ff0bebd0beaaf279e0a18f2b6c0bb5562fc6 100644
--- a/src/mol-canvas3d/canvas3d.ts
+++ b/src/mol-canvas3d/canvas3d.ts
@@ -16,7 +16,7 @@ import TrackballControls from './controls/trackball'
 import { Viewport } from './camera/util'
 import { resizeCanvas } from './util';
 import { createContext, getGLContext, WebGLContext } from 'mol-gl/webgl/context';
-import { Representation } from 'mol-geo/representation';
+import { Representation } from 'mol-repr';
 import { createRenderTarget } from 'mol-gl/webgl/render-target';
 import Scene from 'mol-gl/scene';
 import { RenderVariant } from 'mol-gl/webgl/render-item';
diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts
index 457c6a14db1e9fdcae82fa889966685f43852537..cc66f80c9edd161b5a518d38acab4be1f9faedc1 100644
--- a/src/mol-geo/geometry/color-data.ts
+++ b/src/mol-geo/geometry/color-data.ts
@@ -37,16 +37,17 @@ export interface ColorProps {
 }
 
 export function getColorThemeProps(props: ColorProps): ColorThemeProps {
-    return {
-        name: props.colorTheme,
-        domain: props.colorDomain,
-        value: props.colorValue,
-        structure: props.structure,
-        color: props.colorFunction,
-        granularity: props.colorGranularity,
-        description: props.colorDescription,
-        legend: props.colorLegend
+    const p: ColorThemeProps = {
+        name: props.colorTheme
     }
+    if (props.colorDomain !== undefined) p.domain = props.colorDomain
+    if (props.colorValue !== undefined) p.value = props.colorValue
+    if (props.structure !== undefined) p.structure = props.structure
+    if (props.colorFunction !== undefined) p.color = props.colorFunction
+    if (props.colorGranularity !== undefined) p.granularity = props.colorGranularity
+    if (props.colorDescription !== undefined) p.description = props.colorDescription
+    if (props.colorLegend !== undefined) p.legend = props.colorLegend
+    return p
 }
 
 export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, props: ColorProps, colorData?: ColorData): Promise<ColorData> {
diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts
deleted file mode 100644
index e9ca9e4c26f503cf30a186fa3e4fbf96394c1ce7..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/index.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Task, RuntimeContext } from 'mol-task'
-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-util/parameter';
-
-export interface RepresentationProps {}
-
-export interface Representation<D, P extends RepresentationProps = {}> {
-    readonly label: string
-    readonly params: Params
-    readonly renderObjects: ReadonlyArray<RenderObject>
-    readonly props: Readonly<P>
-    createOrUpdate: (props?: Partial<P>, data?: D) => Task<void>
-    getLoci: (pickingId: PickingId) => Loci
-    mark: (loci: Loci, action: MarkerAction) => boolean
-    destroy: () => void
-}
-
-export interface Visual<D, P extends RepresentationProps = {}> {
-    readonly renderObject: RenderObject | undefined
-    createOrUpdate: (ctx: RuntimeContext, props?: Partial<P>, data?: D) => Promise<void>
-    getLoci: (pickingId: PickingId) => Loci
-    mark: (loci: Loci, action: MarkerAction) => boolean
-    destroy: () => void
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/backbone.ts b/src/mol-geo/representation/structure/representation/backbone.ts
deleted file mode 100644
index ecfa4da0454e3e770b62462e23dd27fdf36724fb..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/backbone.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { StructureRepresentation, UnitsRepresentation } from '..';
-import { PickingId } from '../../../geometry/picking';
-import { Structure } from 'mol-model/structure';
-import { Task } from 'mol-task';
-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-util/parameter';
-
-export const BackboneParams = {
-    ...PolymerBackboneParams
-}
-export const DefaultBackboneProps = paramDefaultValues(BackboneParams)
-export type BackboneProps = typeof DefaultBackboneProps
-
-export type BackboneRepresentation = StructureRepresentation<BackboneProps>
-
-export function BackboneRepresentation(): BackboneRepresentation {
-    const traceRepr = UnitsRepresentation('Polymer backbone cylinder', PolymerBackboneVisual)
-
-    let currentProps: BackboneProps
-    return {
-        label: 'Backbone',
-        params: BackboneParams,
-        get renderObjects() {
-            return [ ...traceRepr.renderObjects ]
-        },
-        get props() {
-            return { ...traceRepr.props }
-        },
-        createOrUpdate: (props: Partial<BackboneProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultBackboneProps, currentProps, props, qualityProps)
-            return Task.create('BackboneRepresentation', async ctx => {
-                await traceRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            return traceRepr.getLoci(pickingId)
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            return traceRepr.mark(loci, action)
-        },
-        destroy() {
-            traceRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/ball-and-stick.ts b/src/mol-geo/representation/structure/representation/ball-and-stick.ts
deleted file mode 100644
index c66376dafe6e723f682efe9f0bed2fb70e7d3540..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/ball-and-stick.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { ComplexRepresentation, StructureRepresentation, UnitsRepresentation } from '..';
-import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere';
-import { IntraUnitLinkVisual, IntraUnitLinkParams } from '../visual/intra-unit-link-cylinder';
-import { PickingId } from '../../../geometry/picking';
-import { Structure } from 'mol-model/structure';
-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-theme/size';
-import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam, MultiSelectParam } from 'mol-util/parameter';
-import { UnitKind, UnitKindOptions } from '../visual/util/common';
-
-export const BallAndStickParams = {
-    ...ElementSphereParams,
-    ...IntraUnitLinkParams,
-    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
-    sizeValue: NumberParam('Size Value', '', 0.2, 0, 10, 0.1),
-    sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1),
-    unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', ['atomic'], UnitKindOptions),
-}
-export const DefaultBallAndStickProps = paramDefaultValues(BallAndStickParams)
-export type BallAndStickProps = typeof DefaultBallAndStickProps
-
-export type BallAndStickRepresentation = StructureRepresentation<BallAndStickProps>
-
-export function BallAndStickRepresentation(): BallAndStickRepresentation {
-    const elmementRepr = UnitsRepresentation('Element sphere mesh', ElementSphereVisual)
-    const intraLinkRepr = UnitsRepresentation('Intra-unit link cylinder', IntraUnitLinkVisual)
-    const interLinkRepr = ComplexRepresentation('Inter-unit link cylinder', InterUnitLinkVisual)
-
-    let currentProps: BallAndStickProps
-    return {
-        label: 'Ball & Stick',
-        params: BallAndStickParams,
-        get renderObjects() {
-            return [ ...elmementRepr.renderObjects, ...intraLinkRepr.renderObjects, ...interLinkRepr.renderObjects ]
-        },
-        get props() {
-            return { ...elmementRepr.props, ...intraLinkRepr.props, ...interLinkRepr.props }
-        },
-        createOrUpdate: (props: Partial<BallAndStickProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultBallAndStickProps, currentProps, props, qualityProps)
-            return Task.create('BallAndStickRepresentation', async ctx => {
-                await elmementRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                await intraLinkRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                await interLinkRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            const sphereLoci = elmementRepr.getLoci(pickingId)
-            const intraLinkLoci = intraLinkRepr.getLoci(pickingId)
-            const interLinkLoci = interLinkRepr.getLoci(pickingId)
-            if (isEmptyLoci(sphereLoci)) {
-                if (isEmptyLoci(intraLinkLoci)) {
-                    return interLinkLoci
-                } else {
-                    return intraLinkLoci
-                }
-            } else {
-                return sphereLoci
-            }
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            const markElement = elmementRepr.mark(loci, action)
-            const markIntraLink = intraLinkRepr.mark(loci, action)
-            const markInterLink = interLinkRepr.mark(loci, action)
-            return markElement || markIntraLink || markInterLink
-        },
-        destroy() {
-            elmementRepr.destroy()
-            intraLinkRepr.destroy()
-            interLinkRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/carbohydrate.ts b/src/mol-geo/representation/structure/representation/carbohydrate.ts
deleted file mode 100644
index e9580f4e0e2c0145d048afadbc25c7af961e6be0..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/carbohydrate.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { ComplexRepresentation, StructureRepresentation } from '..';
-import { PickingId } from '../../../geometry/picking';
-import { Structure } from 'mol-model/structure';
-import { Task } from 'mol-task';
-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-theme/size';
-import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
-
-export const CarbohydrateParams = {
-    ...CarbohydrateSymbolParams,
-    ...CarbohydrateLinkParams,
-    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
-    sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20),
-    sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1),
-}
-export const DefaultCarbohydrateProps = paramDefaultValues(CarbohydrateParams)
-export type CarbohydrateProps = typeof DefaultCarbohydrateProps
-
-export type CarbohydrateRepresentation = StructureRepresentation<CarbohydrateProps>
-
-export function CarbohydrateRepresentation(): CarbohydrateRepresentation {
-    const carbohydrateSymbolRepr = ComplexRepresentation('Carbohydrate symbol mesh', CarbohydrateSymbolVisual)
-    const carbohydrateLinkRepr = ComplexRepresentation('Carbohydrate link cylinder', CarbohydrateLinkVisual)
-
-    let currentProps: CarbohydrateProps
-    return {
-        label: 'Carbohydrate',
-        params: CarbohydrateParams,
-        get renderObjects() {
-            return [ ...carbohydrateSymbolRepr.renderObjects, ...carbohydrateLinkRepr.renderObjects ]
-        },
-        get props() {
-            return { ...carbohydrateSymbolRepr.props, ...carbohydrateLinkRepr.props }
-        },
-        createOrUpdate: (props: Partial<CarbohydrateProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultCarbohydrateProps, currentProps, props, qualityProps)
-            return Task.create('Creating CarbohydrateRepresentation', async ctx => {
-                await carbohydrateSymbolRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                await carbohydrateLinkRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            const carbohydrateSymbolLoci = carbohydrateSymbolRepr.getLoci(pickingId)
-            const carbohydrateLinkLoci = carbohydrateLinkRepr.getLoci(pickingId)
-            return !isEmptyLoci(carbohydrateSymbolLoci) ? carbohydrateSymbolLoci
-                : carbohydrateLinkLoci
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            const markSymbol = carbohydrateSymbolRepr.mark(loci, action)
-            const markLink = carbohydrateLinkRepr.mark(loci, action)
-            return markSymbol || markLink
-        },
-        destroy() {
-            carbohydrateSymbolRepr.destroy()
-            carbohydrateLinkRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/cartoon.ts b/src/mol-geo/representation/structure/representation/cartoon.ts
deleted file mode 100644
index 6083f02330a5136166860fbb7a26fcf088951063..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/cartoon.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { StructureRepresentation, UnitsRepresentation } from '..';
-import { PickingId } from '../../../geometry/picking';
-import { Structure } from 'mol-model/structure';
-import { Task } from 'mol-task';
-import { Loci, isEmptyLoci } from 'mol-model/loci';
-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-theme/size';
-import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
-// import { PolymerDirectionVisual, DefaultPolymerDirectionProps } from '../visual/polymer-direction-wedge';
-
-export const CartoonParams = {
-    ...PolymerTraceParams,
-    ...PolymerGapParams,
-    ...NucleotideBlockParams,
-    // ...PolymerDirectionParams,
-    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
-    sizeValue: NumberParam('Size Value', '', 0.6, 0, 10, 0.1),
-}
-export const DefaultCartoonProps = paramDefaultValues(CartoonParams)
-export type CartoonProps = typeof DefaultCartoonProps
-
-export type CartoonRepresentation = StructureRepresentation<CartoonProps>
-
-export function CartoonRepresentation(): CartoonRepresentation {
-    const traceRepr = UnitsRepresentation('Polymer trace mesh', PolymerTraceVisual)
-    const gapRepr = UnitsRepresentation('Polymer gap cylinder', PolymerGapVisual)
-    const blockRepr = UnitsRepresentation('Nucleotide block mesh', NucleotideBlockVisual)
-    // const directionRepr = UnitsRepresentation('Polymer direction wedge', PolymerDirectionVisual)
-
-    let currentProps: CartoonProps
-    return {
-        label: 'Cartoon',
-        params: CartoonParams,
-        get renderObjects() {
-            return [ ...traceRepr.renderObjects, ...gapRepr.renderObjects,
-                ...blockRepr.renderObjects // , ...directionRepr.renderObjects
-            ]
-        },
-        get props() {
-            return { ...traceRepr.props, ...gapRepr.props, ...blockRepr.props }
-        },
-        createOrUpdate: (props: Partial<CartoonProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultCartoonProps, currentProps, props, qualityProps)
-            return Task.create('Creating CartoonRepresentation', async ctx => {
-                await traceRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                await gapRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                await blockRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-                // await directionRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            const traceLoci = traceRepr.getLoci(pickingId)
-            const gapLoci = gapRepr.getLoci(pickingId)
-            const blockLoci = blockRepr.getLoci(pickingId)
-            // const directionLoci = directionRepr.getLoci(pickingId)
-            return !isEmptyLoci(traceLoci) ? traceLoci
-                : !isEmptyLoci(gapLoci) ? gapLoci
-                : blockLoci
-                // : !isEmptyLoci(blockLoci) ? blockLoci
-                // : directionLoci
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            const markTrace = traceRepr.mark(loci, action)
-            const markGap = gapRepr.mark(loci, action)
-            const markBlock = blockRepr.mark(loci, action)
-            // const markDirection = directionRepr.mark(loci, action)
-            return markTrace || markGap || markBlock // \\ markDirection
-        },
-        destroy() {
-            traceRepr.destroy()
-            gapRepr.destroy()
-            blockRepr.destroy()
-            // directionRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/distance-restraint.ts b/src/mol-geo/representation/structure/representation/distance-restraint.ts
deleted file mode 100644
index d0f5ef74be21df241d0d8507daec121093bc83ae..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/distance-restraint.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { ComplexRepresentation, StructureRepresentation } from '..';
-import { PickingId } from '../../../geometry/picking';
-import { Structure } from 'mol-model/structure';
-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-theme/size';
-import { getQualityProps } from '../../util';
-import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
-
-export const DistanceRestraintParams = {
-    ...CrossLinkRestraintParams,
-    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
-    sizeValue: NumberParam('Size Value', '', 0.25, 0, 0.05, 20),
-}
-export const DefaultDistanceRestraintProps = paramDefaultValues(DistanceRestraintParams)
-export type DistanceRestraintProps = typeof DefaultDistanceRestraintProps
-
-export type DistanceRestraintRepresentation = StructureRepresentation<DistanceRestraintProps>
-
-export function DistanceRestraintRepresentation(): DistanceRestraintRepresentation {
-    const crossLinkRepr = ComplexRepresentation('Cross-link restraint', CrossLinkRestraintVisual)
-
-    let currentProps: DistanceRestraintProps
-    return {
-        label: 'Distance restraint',
-        params: DistanceRestraintParams,
-        get renderObjects() {
-            return [ ...crossLinkRepr.renderObjects ]
-        },
-        get props() {
-            return { ...crossLinkRepr.props }
-        },
-        createOrUpdate: (props: Partial<DistanceRestraintProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultDistanceRestraintProps, currentProps, props, qualityProps)
-            return Task.create('DistanceRestraintRepresentation', async ctx => {
-                await crossLinkRepr.createOrUpdate(currentProps, structure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            return crossLinkRepr.getLoci(pickingId)
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            return crossLinkRepr.mark(loci, action)
-        },
-        destroy() {
-            crossLinkRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/molecular-surface.ts b/src/mol-geo/representation/structure/representation/molecular-surface.ts
deleted file mode 100644
index 355a95d6ea152cb17f760e8314322ca930925789..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/molecular-surface.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { UnitsRepresentation } from '..';
-import { GaussianSurfaceVisual, GaussianSurfaceParams } from '../visual/gaussian-surface-mesh';
-import { StructureRepresentation } from '../units-representation';
-import { Structure } from 'mol-model/structure';
-import { MarkerAction } from '../../../geometry/marker-data';
-import { Loci, isEmptyLoci } from 'mol-model/loci';
-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-util/parameter';
-import { GaussianDensityVolumeParams, GaussianDensityVolumeVisual } from '../visual/gaussian-density-volume';
-import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
-
-const VisualOptions = [['surface', 'Surface'], ['wireframe', 'Wireframe'], ['volume', 'Volume']] as [string, string][]
-
-export const MolecularSurfaceParams = {
-    ...GaussianSurfaceParams,
-    ...GaussianWireframeParams,
-    ...GaussianDensityVolumeParams,
-
-    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
-    visuals: MultiSelectParam<string>('Visuals', '', ['surface'], VisualOptions)
-}
-export const DefaultMolecularSurfaceProps = paramDefaultValues(MolecularSurfaceParams)
-export type MolecularSurfaceProps = typeof DefaultMolecularSurfaceProps
-
-export type MolecularSurfaceRepresentation = StructureRepresentation<MolecularSurfaceProps>
-
-export function MolecularSurfaceRepresentation(): MolecularSurfaceRepresentation {
-    let currentProps: MolecularSurfaceProps
-    let currentStructure: Structure
-    const gaussianSurfaceRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual)
-    const gaussianWireframeRepr = UnitsRepresentation('Gaussian wireframe', GaussianWireframeVisual)
-    const gaussianVolumeRepr = UnitsRepresentation('Gaussian volume', GaussianDensityVolumeVisual)
-    return {
-        label: 'Molecular Surface',
-        params: MolecularSurfaceParams,
-        get renderObjects() {
-            const renderObjects = []
-            if (currentProps.visuals.includes('surface')) renderObjects.push(...gaussianSurfaceRepr.renderObjects)
-            if (currentProps.visuals.includes('wireframe')) renderObjects.push(...gaussianWireframeRepr.renderObjects)
-            if (currentProps.visuals.includes('volume')) renderObjects.push(...gaussianVolumeRepr.renderObjects)
-            return renderObjects
-        },
-        get props() {
-            return { ...gaussianSurfaceRepr.props, ...gaussianWireframeRepr.props, ...gaussianVolumeRepr.props, visuals: currentProps.visuals }
-        },
-        createOrUpdate: (props: Partial<MolecularSurfaceProps> = {}, structure?: Structure) => {
-            if (structure) currentStructure = structure
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentStructure)
-            currentProps = Object.assign({}, DefaultMolecularSurfaceProps, currentProps, props, qualityProps)
-            return Task.create('Creating MolecularSurfaceRepresentation', async ctx => {
-                if (currentProps.visuals.includes('surface')) await gaussianSurfaceRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx)
-                if (currentProps.visuals.includes('wireframe')) await gaussianWireframeRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx)
-                if (currentProps.visuals.includes('volume')) await gaussianVolumeRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx)
-            })
-        },
-        getLoci: (pickingId: PickingId) => {
-            const surfaceLoci = gaussianSurfaceRepr.getLoci(pickingId)
-            const wireframeLoci = gaussianWireframeRepr.getLoci(pickingId)
-            const volumeLoci = gaussianVolumeRepr.getLoci(pickingId)
-            if (isEmptyLoci(surfaceLoci)) {
-                if (isEmptyLoci(wireframeLoci)) {
-                    return volumeLoci
-                } else {
-                    return wireframeLoci
-                }
-            } else {
-                return surfaceLoci
-            }
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            const markSurfaceElement = gaussianSurfaceRepr.mark(loci, action)
-            const markWireframeElement = gaussianWireframeRepr.mark(loci, action)
-            const markVolumeElement = gaussianVolumeRepr.mark(loci, action)
-            return markSurfaceElement || markWireframeElement || markVolumeElement
-        },
-        destroy() {
-            gaussianSurfaceRepr.destroy()
-            gaussianWireframeRepr.destroy()
-            gaussianVolumeRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/point.ts b/src/mol-geo/representation/structure/representation/point.ts
deleted file mode 100644
index 2992e750372136140837430c8b448cb6c1ae1cbb..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/point.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { UnitsRepresentation } from '..';
-import { ElementPointVisual, ElementPointParams } from '../visual/element-point';
-import { StructureRepresentation } from '../units-representation';
-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-util/parameter';
-
-export const PointParams = {
-    ...ElementPointParams,
-}
-export const DefaultPointProps = paramDefaultValues(PointParams)
-export type PointProps = typeof DefaultPointProps
-
-export type PointRepresentation = StructureRepresentation<PointProps>
-
-export function PointRepresentation(): PointRepresentation {
-    let currentProps: PointProps
-    const pointRepr = UnitsRepresentation('Point', ElementPointVisual)
-    return {
-        label: 'Point',
-        params: PointParams,
-        get renderObjects() {
-            return [ ...pointRepr.renderObjects ]
-        },
-        get props() {
-            return { ...pointRepr.props }
-        },
-        createOrUpdate: (props: Partial<PointProps> = {}, structure?: Structure) => {
-            currentProps = Object.assign({}, DefaultPointProps, currentProps, props)
-            return pointRepr.createOrUpdate(currentProps, structure)
-        },
-        getLoci: (pickingId: PickingId) => {
-            return pointRepr.getLoci(pickingId)
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            return pointRepr.mark(loci, action)
-        },
-        destroy() {
-            pointRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/representation/spacefill.ts b/src/mol-geo/representation/structure/representation/spacefill.ts
deleted file mode 100644
index c79ece3e06d47525775ba60cdd35a3fbed168201..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/structure/representation/spacefill.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { UnitsRepresentation } from '..';
-import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere';
-import { StructureRepresentation } from '../units-representation';
-import { Structure } from 'mol-model/structure';
-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-util/parameter';
-
-export const SpacefillParams = {
-    ...ElementSphereParams
-}
-export const DefaultSpacefillProps = paramDefaultValues(SpacefillParams)
-export type SpacefillProps = typeof DefaultSpacefillProps
-
-export type SpacefillRepresentation = StructureRepresentation<SpacefillProps>
-
-export function SpacefillRepresentation(): SpacefillRepresentation {
-    let currentProps: SpacefillProps
-    const sphereRepr = UnitsRepresentation('Sphere mesh', ElementSphereVisual)
-    return {
-        label: 'Spacefill',
-        params: SpacefillParams,
-        get renderObjects() {
-            return [ ...sphereRepr.renderObjects ]
-        },
-        get props() {
-            return { ...sphereRepr.props }
-        },
-        createOrUpdate: (props: Partial<SpacefillProps> = {}, structure?: Structure) => {
-            const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
-            currentProps = Object.assign({}, DefaultSpacefillProps, currentProps, props, qualityProps)
-            return sphereRepr.createOrUpdate(currentProps, structure)
-        },
-        getLoci: (pickingId: PickingId) => {
-            return sphereRepr.getLoci(pickingId)
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            return sphereRepr.mark(loci, action)
-        },
-        destroy() {
-            sphereRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-sphere.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-sphere.ts
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/mol-geo/representation/volume/index.ts b/src/mol-geo/representation/volume/index.ts
deleted file mode 100644
index dcb95d81aa6007052dbf12b82586e119dfb6c681..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/volume/index.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Task } from 'mol-task'
-import { RepresentationProps, Representation, Visual } from '..';
-import { VolumeData } from 'mol-model/volume';
-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-util/parameter';
-
-export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { }
-
-export interface VolumeRepresentation<P extends RepresentationProps = {}> extends Representation<VolumeData, P> { }
-
-export const VolumeParams = {
-    ...Geometry.Params,
-}
-export const DefaultVolumeProps = paramDefaultValues(VolumeParams)
-export type VolumeProps = typeof DefaultVolumeProps
-
-export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeData: VolumeData) => VolumeVisual<P>): VolumeRepresentation<P> {
-    let visual: VolumeVisual<any>
-    let _props: P
-    let busy = false
-
-    function createOrUpdate(props: Partial<P> = {}, volumeData?: VolumeData) {
-        _props = Object.assign({}, DefaultVolumeProps, _props, props)
-        return Task.create('VolumeRepresentation.create', async ctx => {
-            // TODO queue it somehow
-            if (busy) return
-
-            if (!visual && !volumeData) {
-                throw new Error('volumeData missing')
-            } else if (volumeData && !visual) {
-                busy = true
-                visual = visualCtor(volumeData)
-                await visual.createOrUpdate(ctx, props, volumeData)
-                busy = false
-            } else {
-                busy = true
-                await visual.createOrUpdate(ctx, props, volumeData)
-                busy = false
-            }
-        });
-    }
-
-    return {
-        label: 'Volume',
-        params: VolumeParams,
-        get renderObjects() {
-            return visual && visual.renderObject ? [ visual.renderObject ] : []
-        },
-        get props () { return _props },
-        createOrUpdate,
-        getLoci(pickingId: PickingId) {
-            // TODO
-            return EmptyLoci
-        },
-        mark(loci: Loci, action: MarkerAction) {
-            // TODO
-            return false
-        },
-        destroy() {
-            // TODO
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-geo/representation/volume/isosurface-mesh.ts b/src/mol-geo/representation/volume/isosurface-mesh.ts
deleted file mode 100644
index acff269e697040063011363c958f61be524e8f26..0000000000000000000000000000000000000000
--- a/src/mol-geo/representation/volume/isosurface-mesh.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { VolumeData, VolumeIsoValue } from 'mol-model/volume'
-import { RuntimeContext } from 'mol-task'
-import { computeMarchingCubesMesh } from '../../util/marching-cubes/algorithm';
-import { Mesh } from '../../geometry/mesh/mesh';
-import { VolumeVisual, VolumeRepresentation } from '.';
-import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object';
-import { PickingId } from '../../geometry/picking';
-import { MarkerAction } from '../../geometry/marker-data';
-import { Loci, EmptyLoci } from 'mol-model/loci';
-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-util/parameter';
-import { ValueCell } from 'mol-util';
-
-export async function createVolumeSurface(ctx: RuntimeContext, volume: VolumeData, isoValueAbsolute: number, mesh?: Mesh) {
-    ctx.update({ message: 'Marching cubes...' });
-
-    const surface = await computeMarchingCubesMesh({
-        isoLevel: isoValueAbsolute,
-        scalarField: volume.data
-    }, mesh).runAsChild(ctx);
-
-    const transform = VolumeData.getGridToCartesianTransform(volume);
-    ctx.update({ message: 'Transforming mesh...' });
-    Mesh.transformImmediate(surface, transform);
-    Mesh.computeNormalsImmediate(surface)
-
-    return surface;
-}
-
-export const IsosurfaceParams = {
-    ...Mesh.Params,
-    isoValueAbsolute: RangeParam('Iso Value Absolute', '', 0.22, -1, 1, 0.01),
-    isoValueRelative: RangeParam('Iso Value Relative', '', 2, -10, 10, 0.1),
-}
-export const DefaultIsosurfaceProps = paramDefaultValues(IsosurfaceParams)
-export type IsosurfaceProps = typeof DefaultIsosurfaceProps
-
-export function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> {
-    let currentProps = DefaultIsosurfaceProps
-    let renderObject: MeshRenderObject
-    let currentVolume: VolumeData
-    let mesh: Mesh
-
-    async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<IsosurfaceProps> = {}) {
-        currentProps = { ...DefaultIsosurfaceProps, ...props }
-        if (props.isoValueRelative) {
-            currentProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
-            console.log('create props.isoValueRelative', props.isoValueRelative, currentProps.isoValueAbsolute, currentVolume.dataStats)
-        }
-
-        mesh = await createVolumeSurface(ctx, volume, currentProps.isoValueAbsolute)
-
-        const locationIt = LocationIterator(1, 1, () => NullLocation)
-        const transform = createIdentityTransform()
-
-        const values = await Mesh.createValues(ctx, mesh, transform, locationIt, currentProps)
-        const state = createRenderableState(currentProps)
-
-        renderObject = createMeshRenderObject(values, state)
-    }
-
-    async function update(ctx: RuntimeContext, props: Partial<IsosurfaceProps> = {}) {
-        const newProps = { ...currentProps, ...props }
-        if (props.isoValueRelative) {
-            newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
-            console.log('update props.isoValueRelative', props.isoValueRelative, newProps.isoValueAbsolute, currentVolume.dataStats)
-        }
-
-        let createMesh = false
-
-        if (newProps.isoValueAbsolute !== currentProps.isoValueAbsolute) createMesh = true
-
-        if (createMesh) {
-            mesh = await createVolumeSurface(ctx, currentVolume, newProps.isoValueAbsolute, mesh)
-            ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3)
-        }
-
-        Mesh.updateValues(renderObject.values, newProps)
-        updateRenderableState(renderObject.state, newProps)
-
-        currentProps = newProps
-    }
-
-    return {
-        get renderObject () { return renderObject },
-        async createOrUpdate(ctx: RuntimeContext, props: Partial<IsosurfaceProps> = {}, volume?: VolumeData) {
-            if (!volume && !currentVolume) {
-                throw new Error('missing volume')
-            } else if (volume && (!currentVolume || !renderObject)) {
-                currentVolume = volume
-                await create(ctx, volume, props)
-            } else if (volume && volume !== currentVolume) {
-                currentVolume = volume
-                await create(ctx, volume, props)
-            } else {
-                await update(ctx, props)
-            }
-
-            currentProps = { ...DefaultIsosurfaceProps, ...props }
-        },
-        getLoci(pickingId: PickingId) {
-            // TODO
-            return EmptyLoci
-        },
-        mark(loci: Loci, action: MarkerAction) {
-            // TODO
-            return false
-        },
-        destroy() {
-            // TODO
-        }
-    }
-}
-
-export function IsosurfaceRepresentation(): VolumeRepresentation<IsosurfaceProps> {
-    let currentProps: IsosurfaceProps
-    const volumeRepr = VolumeRepresentation(IsosurfaceVisual)
-    return {
-        label: 'Isosurface',
-        params: IsosurfaceParams,
-        get renderObjects() {
-            return [ ...volumeRepr.renderObjects ]
-        },
-        get props() {
-            return { ...volumeRepr.props }
-        },
-        createOrUpdate: (props: Partial<IsosurfaceProps> = {}, volume?: VolumeData) => {
-            currentProps = Object.assign({}, DefaultIsosurfaceProps, currentProps, props)
-            return volumeRepr.createOrUpdate(currentProps, volume)
-        },
-        getLoci: (pickingId: PickingId) => {
-            return volumeRepr.getLoci(pickingId)
-        },
-        mark: (loci: Loci, action: MarkerAction) => {
-            return volumeRepr.mark(loci, action)
-        },
-        destroy() {
-            volumeRepr.destroy()
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mol-plugin/state/objects.ts b/src/mol-plugin/state/objects.ts
index 6550334a3c43ba9db8f3c1516dc94fcc35b51300..c5082458aeec58b855edbfa6d5e81a7e526e4c30 100644
--- a/src/mol-plugin/state/objects.ts
+++ b/src/mol-plugin/state/objects.ts
@@ -7,7 +7,7 @@
 import { PluginStateObject } from './base';
 import { CifFile } from 'mol-io/reader/cif';
 import { Model as _Model, Structure as _Structure } from 'mol-model/structure'
-import { StructureRepresentation } from 'mol-geo/representation/structure';
+import { StructureRepresentation } from 'mol-repr/structure/index';
 
 const _create = PluginStateObject.Create
 
diff --git a/src/mol-plugin/state/transforms/visuals.ts b/src/mol-plugin/state/transforms/visuals.ts
index b1c521865dadc512fb63915ed93f1fc225edc84f..9da25b631f8e6a6d03a2408c82d5fcc8c9d17a6b 100644
--- a/src/mol-plugin/state/transforms/visuals.ts
+++ b/src/mol-plugin/state/transforms/visuals.ts
@@ -4,11 +4,11 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { CartoonRepresentation, DefaultCartoonProps } from 'mol-geo/representation/structure/representation/cartoon';
 import { Transformer } from 'mol-state';
 import { Task } from 'mol-task';
 import { PluginStateTransform } from '../base';
 import { PluginStateObjects as SO } from '../objects';
+import { CartoonRepresentation, DefaultCartoonProps } from 'mol-repr/structure/representation/cartoon';
 
 export const CreateStructureRepresentation = PluginStateTransform.Create<SO.Structure, SO.StructureRepresentation3D, { }>({
     name: 'create-structure-representation',
diff --git a/src/mol-repr/index.ts b/src/mol-repr/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..83a39d2e0423353e61c93229d6c01395b6962e18
--- /dev/null
+++ b/src/mol-repr/index.ts
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Task, RuntimeContext } from 'mol-task'
+import { RenderObject } from 'mol-gl/render-object'
+import { PickingId } from '../mol-geo/geometry/picking';
+import { Loci, isEmptyLoci, EmptyLoci } from 'mol-model/loci';
+import { MarkerAction } from '../mol-geo/geometry/marker-data';
+import { Params, MultiSelectParam } from 'mol-util/parameter';
+
+// export interface RepresentationProps {
+//     visuals?: string[]
+// }
+export type RepresentationProps = { [k: string]: any }
+
+export interface Representation<D, P extends RepresentationProps = {}> {
+    readonly label: string
+    readonly params: Params
+    readonly renderObjects: ReadonlyArray<RenderObject>
+    readonly props: Readonly<P>
+    createOrUpdate: (props?: Partial<P>, data?: D) => Task<void>
+    getLoci: (pickingId: PickingId) => Loci
+    mark: (loci: Loci, action: MarkerAction) => boolean
+    destroy: () => void
+}
+
+export namespace Representation {
+    export function createMulti<D, P extends RepresentationProps = {}>(label: string, params: Params, defaultProps: P, reprList: Representation<D, P>[]): Representation<D, P> {
+        let currentProps: P
+        let currentData: D
+
+        const visualsOptions: [string, string][] = []
+        for (let i = 0, il = reprList.length; i < il; ++i) {
+            visualsOptions.push([ i.toString(), reprList[i].label ])
+        }
+        params['visuals'] = MultiSelectParam<string>('Visuals', '', ['surface'], visualsOptions)
+
+        if (!defaultProps.visuals) {
+            defaultProps.visuals = reprList.map((r, i) => i.toString())
+        }
+
+        return {
+            label,
+            params,
+            get renderObjects() {
+                const { visuals } = currentProps
+                const renderObjects: RenderObject[] = []
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    if (!visuals || visuals.includes(i.toString())) {
+                        renderObjects.push(...reprList[i].renderObjects)
+                    }
+                }
+                return renderObjects
+            },
+            get props() {
+                const props = {}
+                reprList.forEach(r => Object.assign(props, r.props))
+                return props as P
+            },
+            createOrUpdate: (props: Partial<P> = {}, data?: D) => {
+                if (data) currentData = data
+                // const qualityProps = getQualityProps(Object.assign({}, currentProps, props), structure)
+                // currentProps = Object.assign({}, DefaultCartoonProps, currentProps, props, qualityProps)
+                currentProps = Object.assign({}, defaultProps, currentProps, props)
+
+                const { visuals } = currentProps
+                return Task.create(`Creating '${label}' representation`, async ctx => {
+                    for (let i = 0, il = reprList.length; i < il; ++i) {
+                        if (!visuals || visuals.includes(i.toString())) {
+                            await reprList[i].createOrUpdate(currentProps, currentData).runInContext(ctx)
+                        }
+                    }
+                })
+            },
+            getLoci: (pickingId: PickingId) => {
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    const loci = reprList[i].getLoci(pickingId)
+                    if (!isEmptyLoci(loci)) return loci
+                }
+                return EmptyLoci
+            },
+            mark: (loci: Loci, action: MarkerAction) => {
+                let marked = false
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    marked = reprList[i].mark(loci, action) || marked
+                }
+                return marked
+            },
+            destroy() {
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    reprList[i].destroy()
+                }
+            }
+        }
+    }
+}
+
+export interface Visual<D, P extends RepresentationProps> {
+    readonly renderObject: RenderObject | undefined
+    createOrUpdate: (ctx: RuntimeContext, props?: Partial<P>, data?: D) => Promise<void>
+    getLoci: (pickingId: PickingId) => Loci
+    mark: (loci: Loci, action: MarkerAction) => boolean
+    destroy: () => void
+}
\ No newline at end of file
diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-repr/shape/index.ts
similarity index 91%
rename from src/mol-geo/representation/shape/index.ts
rename to src/mol-repr/shape/index.ts
index 529b67b8d78047da60a2177e1d8fdac288b6ad80..a953f8ecc75edb35c2504a38412bfe3372fea80c 100644
--- a/src/mol-geo/representation/shape/index.ts
+++ b/src/mol-repr/shape/index.ts
@@ -7,18 +7,18 @@
 import { Task } from 'mol-task'
 import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object';
 import { RepresentationProps, Representation } from '..';
-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-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-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { createIdentityTransform } from 'mol-geo/geometry/transform-data';
+import { createRenderableState } from 'mol-geo/geometry/geometry';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
 
 export interface ShapeRepresentation<P extends RepresentationProps = {}> extends Representation<Shape, P> { }
 
diff --git a/src/mol-geo/representation/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts
similarity index 92%
rename from src/mol-geo/representation/structure/complex-representation.ts
rename to src/mol-repr/structure/complex-representation.ts
index cf59bb872b50a527109d3eabeb41cdc8b6bbeda9..77dc1ac957bf8bdc3f8697fe096748ae47746ed2 100644
--- a/src/mol-geo/representation/structure/complex-representation.ts
+++ b/src/mol-repr/structure/complex-representation.ts
@@ -7,11 +7,11 @@
 
 import { Structure } from 'mol-model/structure';
 import { Task } from 'mol-task'
-import { PickingId } from '../../geometry/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { MarkerAction } from '../../geometry/marker-data';
-import { StructureProps, StructureRepresentation, StructureParams } from '.';
+import { StructureProps, StructureRepresentation, StructureParams } from './index';
 import { ComplexVisual } from './complex-visual';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction } from 'mol-geo/geometry/marker-data';
 
 export function ComplexRepresentation<P extends StructureProps>(label: string, visualCtor: () => ComplexVisual<P>): StructureRepresentation<P> {
     let visual: ComplexVisual<P> | undefined
diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts
similarity index 92%
rename from src/mol-geo/representation/structure/complex-visual.ts
rename to src/mol-repr/structure/complex-visual.ts
index aac01779c41a402b9e710bda94e7d9390152a064..4e7acbf7577d1647079ff316b606b4d2392cacc6 100644
--- a/src/mol-geo/representation/structure/complex-visual.ts
+++ b/src/mol-repr/structure/complex-visual.ts
@@ -7,21 +7,22 @@
 import { Structure } from 'mol-model/structure';
 import { Visual } from '..';
 import { MeshRenderObject, LinesRenderObject, PointsRenderObject, DirectVolumeRenderObject } from 'mol-gl/render-object';
-import { Mesh } from '../../geometry/mesh/mesh';
 import { RuntimeContext } from 'mol-task';
-import { LocationIterator } from '../../util/location-iterator';
-import { createComplexMeshRenderObject, sizeChanged, colorChanged, UnitKind, UnitKindOptions } from './visual/util/common';
-import { StructureProps, VisualUpdateState, StructureMeshParams, StructureParams } from '.';
+import { createComplexMeshRenderObject, UnitKind, UnitKindOptions } from './visual/util/common';
+import { StructureProps, StructureMeshParams, StructureParams } from './index';
 import { deepEqual, ValueCell } from 'mol-util';
-import { PickingId } from '../../geometry/picking';
 import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci';
-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-util/parameter';
 import { RenderableValues } from 'mol-gl/renderable/schema';
 import { createSizes } from 'mol-geo/geometry/size-data';
+import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { createColors } from 'mol-geo/geometry/color-data';
+import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { VisualUpdateState, colorChanged, sizeChanged } from 'mol-repr/util';
 
 export interface  ComplexVisual<P extends StructureProps> extends Visual<Structure, P> { }
 
diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-repr/structure/index.ts
similarity index 70%
rename from src/mol-geo/representation/structure/index.ts
rename to src/mol-repr/structure/index.ts
index a1822294dcc23c42808cb0fedc553cf43d92360e..03a58d51a0eddd5c3bc25070febb27154eaf77ea 100644
--- a/src/mol-geo/representation/structure/index.ts
+++ b/src/mol-repr/structure/index.ts
@@ -9,18 +9,19 @@ import { Structure } from 'mol-model/structure';
 import { ColorThemeName, ColorThemeOptions } from 'mol-theme/color';
 import { SizeThemeName, SizeThemeOptions } from 'mol-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-util/parameter';
-import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
+import { Geometry } from 'mol-geo/geometry/geometry';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { Points } from 'mol-geo/geometry/points/points';
+import { Lines } from 'mol-geo/geometry/lines/lines';
+import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume';
 
 export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
+// export interface  StructureVisual<P extends RepresentationProps = {}> extends Visual<Structure, P> { }
 
 export const StructureParams = {
     ...Geometry.Params,
-    colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'unit-index', ColorThemeOptions),
+    colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'polymer-index', ColorThemeOptions),
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions),
 }
 export const DefaultStructureProps = paramDefaultValues(StructureParams)
@@ -54,29 +55,6 @@ export const StructureDirectVolumeParams = {
 export const DefaultStructureDirectVolumeProps = paramDefaultValues(StructureDirectVolumeParams)
 export type StructureDirectVolumeProps = typeof DefaultStructureDirectVolumeProps
 
-export interface VisualUpdateState {
-    updateTransform: boolean
-    updateColor: boolean
-    updateSize: boolean
-    createGeometry: boolean
-}
-export namespace VisualUpdateState {
-    export function create(): VisualUpdateState {
-        return {
-            updateTransform: false,
-            updateColor: false,
-            updateSize: false,
-            createGeometry: false
-        }
-    }
-    export function reset(state: VisualUpdateState) {
-        state.updateTransform = false
-        state.updateColor = false
-        state.updateSize = false
-        state.createGeometry = false
-    }
-}
-
 export { ComplexRepresentation } from './complex-representation'
 export { UnitsRepresentation } from './units-representation'
 export { ComplexVisual } from './complex-visual'
diff --git a/src/mol-repr/structure/representation/backbone.ts b/src/mol-repr/structure/representation/backbone.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eea531a2eb38bc38130ec0e6efdba6bd865b85aa
--- /dev/null
+++ b/src/mol-repr/structure/representation/backbone.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { PolymerBackboneVisual, PolymerBackboneParams } from '../visual/polymer-backbone-cylinder';
+import { paramDefaultValues } from 'mol-util/parameter';
+import { UnitsRepresentation } from '../units-representation';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const BackboneParams = {
+    ...PolymerBackboneParams
+}
+export const DefaultBackboneProps = paramDefaultValues(BackboneParams)
+export type BackboneProps = typeof DefaultBackboneProps
+
+export type BackboneRepresentation = StructureRepresentation<BackboneProps>
+
+export function BackboneRepresentation(): BackboneRepresentation {
+    return Representation.createMulti('Backbone', BackboneParams, DefaultBackboneProps, [
+        UnitsRepresentation('Polymer backbone cylinder', PolymerBackboneVisual)
+    ] as StructureRepresentation<BackboneProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/ball-and-stick.ts b/src/mol-repr/structure/representation/ball-and-stick.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f4271f3a803887ec32ba5bba9d5e9749b38dc996
--- /dev/null
+++ b/src/mol-repr/structure/representation/ball-and-stick.ts
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere';
+import { IntraUnitLinkVisual, IntraUnitLinkParams } from '../visual/intra-unit-link-cylinder';
+import { InterUnitLinkVisual, InterUnitLinkParams } from '../visual/inter-unit-link-cylinder';
+import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
+import { paramDefaultValues, SelectParam, NumberParam, MultiSelectParam } from 'mol-util/parameter';
+import { UnitKind, UnitKindOptions } from '../visual/util/common';
+import { UnitsRepresentation } from '../units-representation';
+import { ComplexRepresentation } from '../complex-representation';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const BallAndStickParams = {
+    ...ElementSphereParams,
+    ...IntraUnitLinkParams,
+    ...InterUnitLinkParams,
+    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
+    sizeValue: NumberParam('Size Value', '', 0.2, 0, 10, 0.1),
+    sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1),
+    unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', ['atomic'], UnitKindOptions),
+}
+export const DefaultBallAndStickProps = paramDefaultValues(BallAndStickParams)
+export type BallAndStickProps = typeof DefaultBallAndStickProps
+
+export type BallAndStickRepresentation = StructureRepresentation<BallAndStickProps>
+
+export function BallAndStickRepresentation(): BallAndStickRepresentation {
+    return Representation.createMulti('Ball & Stick', BallAndStickParams, DefaultBallAndStickProps, [
+        UnitsRepresentation('Element sphere mesh', ElementSphereVisual),
+        UnitsRepresentation('Intra-unit link cylinder', IntraUnitLinkVisual),
+        ComplexRepresentation('Inter-unit link cylinder', InterUnitLinkVisual)
+    ] as unknown as StructureRepresentation<BallAndStickProps>[]) // TODO avoid cast to unknown
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/carbohydrate.ts b/src/mol-repr/structure/representation/carbohydrate.ts
new file mode 100644
index 0000000000000000000000000000000000000000..941fda8878243123069dfae22f20fd0df4e1b20e
--- /dev/null
+++ b/src/mol-repr/structure/representation/carbohydrate.ts
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { CarbohydrateSymbolVisual, CarbohydrateSymbolParams } from '../visual/carbohydrate-symbol-mesh';
+import { CarbohydrateLinkVisual, CarbohydrateLinkParams } from '../visual/carbohydrate-link-cylinder';
+import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
+import { ComplexRepresentation } from '../complex-representation';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const CarbohydrateParams = {
+    ...CarbohydrateSymbolParams,
+    ...CarbohydrateLinkParams,
+    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
+    sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20),
+    sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1),
+}
+export const DefaultCarbohydrateProps = paramDefaultValues(CarbohydrateParams)
+export type CarbohydrateProps = typeof DefaultCarbohydrateProps
+
+export type CarbohydrateRepresentation = StructureRepresentation<CarbohydrateProps>
+
+export function CarbohydrateRepresentation(): CarbohydrateRepresentation {
+    return Representation.createMulti('Carbohydrate', CarbohydrateParams, DefaultCarbohydrateProps, [
+        ComplexRepresentation('Carbohydrate symbol mesh', CarbohydrateSymbolVisual),
+        ComplexRepresentation('Carbohydrate link cylinder', CarbohydrateLinkVisual)
+    ] as StructureRepresentation<CarbohydrateProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/cartoon.ts b/src/mol-repr/structure/representation/cartoon.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a4e48bb0ed2fb78aa0ff5397d36c414fd721389
--- /dev/null
+++ b/src/mol-repr/structure/representation/cartoon.ts
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+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-theme/size';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
+import { UnitsRepresentation } from '../units-representation';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+// import { PolymerDirectionVisual, DefaultPolymerDirectionProps } from '../visual/polymer-direction-wedge';
+
+export const CartoonParams = {
+    ...PolymerTraceParams,
+    ...PolymerGapParams,
+    ...NucleotideBlockParams,
+    // ...PolymerDirectionParams,
+    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
+    sizeValue: NumberParam('Size Value', '', 0.6, 0, 10, 0.1),
+}
+export const DefaultCartoonProps = paramDefaultValues(CartoonParams)
+export type CartoonProps = typeof DefaultCartoonProps
+
+export type CartoonRepresentation = StructureRepresentation<CartoonProps>
+
+export function CartoonRepresentation(): CartoonRepresentation {
+    return Representation.createMulti('Cartoon', CartoonParams, DefaultCartoonProps, [
+        UnitsRepresentation('Polymer trace mesh', PolymerTraceVisual),
+        UnitsRepresentation('Polymer gap cylinder', PolymerGapVisual),
+        UnitsRepresentation('Nucleotide block mesh', NucleotideBlockVisual),
+        // UnitsRepresentation('Polymer direction wedge', PolymerDirectionVisual)
+    ] as StructureRepresentation<CartoonProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/distance-restraint.ts b/src/mol-repr/structure/representation/distance-restraint.ts
new file mode 100644
index 0000000000000000000000000000000000000000..28509b3fb78b9313c53d969e70eb35134ad9c1d2
--- /dev/null
+++ b/src/mol-repr/structure/representation/distance-restraint.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { CrossLinkRestraintVisual, CrossLinkRestraintParams } from '../visual/cross-link-restraint-cylinder';
+import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
+import { paramDefaultValues, SelectParam, NumberParam } from 'mol-util/parameter';
+import { ComplexRepresentation } from '../complex-representation';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const DistanceRestraintParams = {
+    ...CrossLinkRestraintParams,
+    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
+    sizeValue: NumberParam('Size Value', '', 0.25, 0, 0.05, 20),
+}
+export const DefaultDistanceRestraintProps = paramDefaultValues(DistanceRestraintParams)
+export type DistanceRestraintProps = typeof DefaultDistanceRestraintProps
+
+export type DistanceRestraintRepresentation = StructureRepresentation<DistanceRestraintProps>
+
+export function DistanceRestraintRepresentation(): DistanceRestraintRepresentation {
+    return Representation.createMulti('Distance restraint', DistanceRestraintParams, DefaultDistanceRestraintProps, [
+        ComplexRepresentation('Cross-link restraint', CrossLinkRestraintVisual)
+    ] as StructureRepresentation<DistanceRestraintProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/molecular-surface.ts b/src/mol-repr/structure/representation/molecular-surface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eed341e26444bc8ae41c7791e9f317c6511f4944
--- /dev/null
+++ b/src/mol-repr/structure/representation/molecular-surface.ts
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { GaussianSurfaceVisual, GaussianSurfaceParams } from '../visual/gaussian-surface-mesh';
+import { UnitsRepresentation } from '../units-representation';
+import { GaussianWireframeVisual, GaussianWireframeParams } from '../visual/gaussian-surface-wireframe';
+import { paramDefaultValues, SelectParam } from 'mol-util/parameter';
+import { GaussianDensityVolumeParams, GaussianDensityVolumeVisual } from '../visual/gaussian-density-volume';
+import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const MolecularSurfaceParams = {
+    ...GaussianSurfaceParams,
+    ...GaussianWireframeParams,
+    ...GaussianDensityVolumeParams,
+    sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
+}
+export const DefaultMolecularSurfaceProps = { ...paramDefaultValues(MolecularSurfaceParams), visuals: [ '0' ] }
+export type MolecularSurfaceProps = typeof DefaultMolecularSurfaceProps
+
+export type MolecularSurfaceRepresentation = StructureRepresentation<MolecularSurfaceProps>
+
+export function MolecularSurfaceRepresentation(): MolecularSurfaceRepresentation {
+    return Representation.createMulti('Molecular Surface', MolecularSurfaceParams, DefaultMolecularSurfaceProps, [
+        UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual),
+        UnitsRepresentation('Gaussian wireframe', GaussianWireframeVisual),
+        UnitsRepresentation('Gaussian volume', GaussianDensityVolumeVisual)
+    ] as unknown as StructureRepresentation<MolecularSurfaceProps>[]) // TODO avoid cast to unknown
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/point.ts b/src/mol-repr/structure/representation/point.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fc4637af4c817ec2ba787d5a8f9fdc099db4085a
--- /dev/null
+++ b/src/mol-repr/structure/representation/point.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { ElementPointVisual, ElementPointParams } from '../visual/element-point';
+import { UnitsRepresentation } from '../units-representation';
+import { paramDefaultValues } from 'mol-util/parameter';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const PointParams = {
+    ...ElementPointParams,
+}
+export const DefaultPointProps = paramDefaultValues(PointParams)
+export type PointProps = typeof DefaultPointProps
+
+export type PointRepresentation = StructureRepresentation<PointProps>
+
+export function PointRepresentation(): PointRepresentation {
+    return Representation.createMulti('Point', PointParams, DefaultPointProps, [
+        UnitsRepresentation('Point', ElementPointVisual)
+    ] as StructureRepresentation<PointProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/spacefill.ts b/src/mol-repr/structure/representation/spacefill.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d5a19bcc1d3352d7efd30c49ae8b5f50fde88713
--- /dev/null
+++ b/src/mol-repr/structure/representation/spacefill.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere';
+import { UnitsRepresentation } from '../units-representation';
+import { paramDefaultValues } from 'mol-util/parameter';
+import { StructureRepresentation } from '../index';
+import { Representation } from 'mol-repr';
+
+export const SpacefillParams = {
+    ...ElementSphereParams
+}
+export const DefaultSpacefillProps = paramDefaultValues(SpacefillParams)
+export type SpacefillProps = typeof DefaultSpacefillProps
+
+export type SpacefillRepresentation = StructureRepresentation<SpacefillProps>
+
+export function SpacefillRepresentation(): SpacefillRepresentation {
+    return Representation.createMulti('Spacefill', SpacefillParams, DefaultSpacefillProps, [
+        UnitsRepresentation('Sphere mesh', ElementSphereVisual)
+    ] as StructureRepresentation<SpacefillProps>[])
+}
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts
similarity index 93%
rename from src/mol-geo/representation/structure/units-representation.ts
rename to src/mol-repr/structure/units-representation.ts
index c2be322d7d5976c9fa1a3f47a3e8b45736423c90..d0694f68ab48a9c4a9ead72c3ae11904c602032d 100644
--- a/src/mol-geo/representation/structure/units-representation.ts
+++ b/src/mol-repr/structure/units-representation.ts
@@ -8,17 +8,14 @@
 import { Structure, Unit } from 'mol-model/structure';
 import { Task } from 'mol-task'
 import { RenderObject } from 'mol-gl/render-object';
-import { Representation, RepresentationProps, Visual } from '..';
-import { PickingId } from '../../geometry/picking';
+import { RepresentationProps, Visual } from '..';
 import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci';
-import { MarkerAction } from '../../geometry/marker-data';
-import { StructureProps, StructureParams } from '.';
 import { StructureGroup } from './units-visual';
+import { StructureProps, StructureParams, StructureRepresentation } from './index';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction } from 'mol-geo/geometry/marker-data';
 
 export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { }
-export interface  StructureVisual<P extends RepresentationProps = {}> extends Visual<Structure, P> { }
-
-export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
 
 export function UnitsRepresentation<P extends StructureProps>(label: string, visualCtor: () => UnitsVisual<P>): StructureRepresentation<P> {
     let visuals = new Map<number, { group: Unit.SymmetryGroup, visual: UnitsVisual<P> }>()
diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts
similarity index 93%
rename from src/mol-geo/representation/structure/units-visual.ts
rename to src/mol-repr/structure/units-visual.ts
index bef61d53306551b03c7e018873286aa8dbf67d03..641d232f6fe2e09783a2e4be3a88891109b01c3d 100644
--- a/src/mol-geo/representation/structure/units-visual.ts
+++ b/src/mol-repr/structure/units-visual.ts
@@ -6,25 +6,26 @@
 
 import { Unit, Structure } from 'mol-model/structure';
 import { RepresentationProps, Visual } from '../';
-import { VisualUpdateState, StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams, StructureParams } from '.';
+import { StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams, StructureParams } from './index';
 import { RuntimeContext } from 'mol-task';
-import { PickingId } from '../../geometry/picking';
-import { LocationIterator } from '../../util/location-iterator';
-import { Mesh } from '../../geometry/mesh/mesh';
-import { MarkerAction, applyMarkerAction, createMarkers } from '../../geometry/marker-data';
 import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci';
 import { MeshRenderObject, PointsRenderObject, LinesRenderObject, DirectVolumeRenderObject } from 'mol-gl/render-object';
-import { createUnitsMeshRenderObject, createUnitsPointsRenderObject, createUnitsTransform, createUnitsLinesRenderObject, createUnitsDirectVolumeRenderObject, UnitKind, UnitKindOptions, includesUnitKind, colorChanged, sizeChanged } from './visual/util/common';
+import { createUnitsMeshRenderObject, createUnitsPointsRenderObject, createUnitsTransform, createUnitsLinesRenderObject, createUnitsDirectVolumeRenderObject, UnitKind, UnitKindOptions, includesUnitKind } from './visual/util/common';
 import { deepEqual, ValueCell, UUID } from 'mol-util';
 import { Interval } from 'mol-data/int';
-import { Points } from '../../geometry/points/points';
-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-util/parameter';
-import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 import { RenderableValues } from 'mol-gl/renderable/schema';
+import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { createMarkers, MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data';
+import { createSizes } from 'mol-geo/geometry/size-data';
+import { createColors } from 'mol-geo/geometry/color-data';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { Points } from 'mol-geo/geometry/points/points';
+import { Lines } from 'mol-geo/geometry/lines/lines';
+import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume';
+import { VisualUpdateState, colorChanged, sizeChanged } from 'mol-repr/util';
 
 export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup }
 
diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
similarity index 95%
rename from src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
rename to src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
index acfb00dc090a69f2bdb30239f95513db302f9e91..8babf03f724fb46b27db2e0a4359956aab8e4a94 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
@@ -5,21 +5,21 @@
  */
 
 import { Structure, Link, StructureElement } from 'mol-model/structure';
-import { ComplexVisual, VisualUpdateState } from '..';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { PickingId } from '../../../geometry/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { Vec3 } from 'mol-math/linear-algebra';
-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 { ComplexMeshVisual, ComplexVisual } from '../complex-visual';
 import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-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-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { VisualUpdateState } from '../../util';
 
 // 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-repr/structure/visual/carbohydrate-symbol-mesh.ts
similarity index 89%
rename from src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
rename to src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts
index b6f6b0e29e54f3b113f34b0ec729875be9f99f29..806fbd4dd35ce671beb618f44421725660902243 100644
--- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
+++ b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts
@@ -4,26 +4,27 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
+import { Mat4, Vec3 } from 'mol-math/linear-algebra';
+import { Box, PerforatedBox } from 'mol-geo/primitive/box';
+import { OctagonalPyramid, PerforatedOctagonalPyramid } from 'mol-geo/primitive/pyramid';
+import { Star } from 'mol-geo/primitive/star';
+import { Octahedron, PerforatedOctahedron } from 'mol-geo/primitive/octahedron';
+import { DiamondPrism, PentagonalPrism, HexagonalPrism } from 'mol-geo/primitive/prism';
+import { RuntimeContext } from 'mol-task';
 import { Structure, StructureElement } from 'mol-model/structure';
-import { ComplexVisual, VisualUpdateState } from '..';
-import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { PickingId } from '../../../geometry/picking';
-import { Loci, EmptyLoci } from 'mol-model/loci';
-import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
-import { Vec3, Mat4 } from 'mol-math/linear-algebra';
-import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants';
-import { LocationIterator } from '../../../util/location-iterator';
-import { OrderedSet, Interval } from 'mol-data/int';
-import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
 import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-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 { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants';
+import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere';
+import { ComplexMeshParams, ComplexMeshVisual } from '../complex-visual';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { ComplexVisual } from '../index';
+import { VisualUpdateState } from '../../util';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { OrderedSet, Interval } from 'mol-data/int';
+import { EmptyLoci, Loci } from 'mol-model/loci';
 
 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-repr/structure/visual/cross-link-restraint-cylinder.ts
similarity index 94%
rename from src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
rename to src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts
index 21eb9879542cf73d60fdf782745fa77fd567505c..e71655c2a555c7d0f80dfbbf993fc9f066d102d8 100644
--- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
+++ b/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts
@@ -5,20 +5,21 @@
  */
 
 import { Link, Structure, StructureElement } from 'mol-model/structure';
-import { ComplexVisual, VisualUpdateState } from '..';
+import { ComplexVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
 import { LinkCylinderProps, createLinkCylinderMesh, LinkCylinderParams } from './util/link';
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { PickingId } from '../../../geometry/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 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-theme/size';
 import { BitFlags } from 'mol-util';
 import { LinkType } from 'mol-model/structure/model/types';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
 
 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-repr/structure/visual/element-point.ts
similarity index 90%
rename from src/mol-geo/representation/structure/visual/element-point.ts
rename to src/mol-repr/structure/visual/element-point.ts
index 5bbb7f4fec3b054a26e64b839864226f037a7c00..d770bb0af5b2d42da434b1e9ed398f3703c5f870 100644
--- a/src/mol-geo/representation/structure/visual/element-point.ts
+++ b/src/mol-repr/structure/visual/element-point.ts
@@ -6,14 +6,15 @@
 
 import { Unit, Structure } from 'mol-model/structure';
 import { RuntimeContext } from 'mol-task'
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { getElementLoci, StructureElementIterator, markElement } from './util/element';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { SizeThemeOptions, SizeThemeName } from 'mol-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-util/parameter';
+import { Points } from 'mol-geo/geometry/points/points';
+import { PointsBuilder } from 'mol-geo/geometry/points/points-builder';
 
 export const ElementPointParams = {
     ...UnitsPointsParams,
diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-repr/structure/visual/element-sphere.ts
similarity index 94%
rename from src/mol-geo/representation/structure/visual/element-sphere.ts
rename to src/mol-repr/structure/visual/element-sphere.ts
index 5d8cbbb8b9a568b63b07064fd418bf953513d2b8..abb930830be9596d73f3c7a5c512c77a9f909a80 100644
--- a/src/mol-geo/representation/structure/visual/element-sphere.ts
+++ b/src/mol-repr/structure/visual/element-sphere.ts
@@ -5,7 +5,8 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
 import { NumberParam, paramDefaultValues, SelectParam } from 'mol-util/parameter';
diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts b/src/mol-repr/structure/visual/gaussian-density-point.ts
similarity index 93%
rename from src/mol-geo/representation/structure/visual/gaussian-density-point.ts
rename to src/mol-repr/structure/visual/gaussian-density-point.ts
index a6a1ec839ad90b00f0107a20de788d2489ae1964..c4bfbc40208c7206a085bb865febfd626b981075 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts
+++ b/src/mol-repr/structure/visual/gaussian-density-point.ts
@@ -6,16 +6,17 @@
 
 import { Unit, Structure } from 'mol-model/structure';
 import { RuntimeContext } from 'mol-task'
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { StructureElementIterator } from './util/element';
 import { EmptyLoci } from 'mol-model/loci';
 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-theme/size';
 import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density';
 import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-util/parameter';
+import { Points } from 'mol-geo/geometry/points/points';
+import { PointsBuilder } from 'mol-geo/geometry/points/points-builder';
 
 export const GaussianDensityPointParams = {
     ...UnitsPointsParams,
diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts b/src/mol-repr/structure/visual/gaussian-density-volume.ts
similarity index 94%
rename from src/mol-geo/representation/structure/visual/gaussian-density-volume.ts
rename to src/mol-repr/structure/visual/gaussian-density-volume.ts
index 912c07dff46006c4f74baebb03f9ef1c38257ad2..4179da8c11a01950daaf31575f434e9421c17a9e 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-density-volume.ts
+++ b/src/mol-repr/structure/visual/gaussian-density-volume.ts
@@ -5,13 +5,14 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 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-util/parameter';
-import { DirectVolume } from '../../../geometry/direct-volume/direct-volume';
+import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume';
 
 async function createGaussianDensityVolume(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> {
     const { webgl } = props
diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts
similarity index 91%
rename from src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts
rename to src/mol-repr/structure/visual/gaussian-surface-mesh.ts
index 8faf356ab1290a11f262fed6744dba611f506e89..7982008eb57523049b55eb80474a830e4d558f1e 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts
+++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts
@@ -5,14 +5,15 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
 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-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm';
 
 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-repr/structure/visual/gaussian-surface-wireframe.ts
similarity index 92%
rename from src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts
rename to src/mol-repr/structure/visual/gaussian-surface-wireframe.ts
index c59b4bcf2f40d726c077c96ef8e772c2b877458d..beb21243742d43009bf4c8ae9600ae6978b11ff4 100644
--- a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts
+++ b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts
@@ -5,15 +5,16 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
 import { UnitsLinesVisual, UnitsLinesParams } from '../units-visual';
 import { StructureElementIterator, getElementLoci, markElement } from './util/element';
-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-util/parameter';
 import { SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
+import { Lines } from 'mol-geo/geometry/lines/lines';
+import { computeMarchingCubesLines } from 'mol-geo/util/marching-cubes/algorithm';
 
 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-repr/structure/visual/inter-unit-link-cylinder.ts
similarity index 95%
rename from src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
rename to src/mol-repr/structure/visual/inter-unit-link-cylinder.ts
index bf4c66294f8267aec5f566498e7fa66ac126321c..4f2c957086e467c4abf67579331bbb4c2c396131 100644
--- a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts
@@ -5,11 +5,10 @@
  */
 
 import { Link, Structure, StructureElement } from 'mol-model/structure';
-import { ComplexVisual, VisualUpdateState } from '..';
+import { ComplexVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
 import { LinkCylinderProps, createLinkCylinderMesh, LinkIterator, LinkCylinderParams } from './util/link';
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { PickingId } from '../../../geometry/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual';
@@ -17,6 +16,8 @@ import { Interval } from 'mol-data/int';
 import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
 import { BitFlags } from 'mol-util';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { PickingId } from 'mol-geo/geometry/picking';
 
 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-repr/structure/visual/intra-unit-link-cylinder.ts
similarity index 96%
rename from src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
rename to src/mol-repr/structure/visual/intra-unit-link-cylinder.ts
index f3a19843a6266ea9ca125d14a010b3ec7bff74a3..97179ec276ec08c01494f8569a38bdb1882095ed 100644
--- a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts
@@ -6,11 +6,10 @@
  */
 
 import { Unit, Link, StructureElement, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
 import { LinkCylinderProps, createLinkCylinderMesh, LinkIterator, LinkCylinderParams } from './util/link';
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { PickingId } from '../../../geometry/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual';
@@ -18,6 +17,8 @@ import { Interval } from 'mol-data/int';
 import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-theme/size';
 import { BitFlags } from 'mol-util';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { PickingId } from 'mol-geo/geometry/picking';
 
 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-repr/structure/visual/nucleotide-block-mesh.ts
similarity index 95%
rename from src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts
rename to src/mol-repr/structure/visual/nucleotide-block-mesh.ts
index 0f80fb2687375a1027fa9fdef5e71088c34bf7ac..f7c0aa0a32a29330c4b2ebf8e2a82d19f2b40296 100644
--- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts
+++ b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts
@@ -5,19 +5,19 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual } from '..';
+import { UnitsVisual } from '../index';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Segmentation } from 'mol-data/int';
 import { MoleculeType, isNucleic, isPurinBase, isPyrimidineBase } from 'mol-model/structure/model/types';
 import { getElementIndexForAtomRole } from 'mol-model/structure/util';
 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-util/parameter';
+import { Box } from 'mol-geo/primitive/box';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder';
 
 const p1 = Vec3.zero()
 const p2 = Vec3.zero()
diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
similarity index 91%
rename from src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts
rename to src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
index 95ccb9311063f615e627de3896a3b4ce57a59eef..b43c0dfc2231fdd5ae7c89c63c9dab192ec6e79f 100644
--- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts
+++ b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
@@ -5,19 +5,20 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
 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-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-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { CylinderProps } from 'mol-geo/primitive/cylinder';
+import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder';
 
 export const PolymerBackboneCylinderParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
diff --git a/src/mol-repr/structure/visual/polymer-backbone-sphere.ts b/src/mol-repr/structure/visual/polymer-backbone-sphere.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ffdd02fcbce683e436c0030ffe0517135c6ceda
--- /dev/null
+++ b/src/mol-repr/structure/visual/polymer-backbone-sphere.ts
@@ -0,0 +1 @@
+// TODO
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts b/src/mol-repr/structure/visual/polymer-direction-wedge.ts
similarity index 95%
rename from src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts
rename to src/mol-repr/structure/visual/polymer-direction-wedge.ts
index eb2a9f926323c661c565422cf67ff41d0228741a..68049ec37d1758e163325661e536927721b7d7b7 100644
--- a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts
+++ b/src/mol-repr/structure/visual/polymer-direction-wedge.ts
@@ -5,17 +5,17 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual } from '..';
+import { UnitsVisual } from '../index';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-import { MeshBuilder } from '../../../geometry/mesh/mesh-builder';
 import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer';
 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-theme/size';
-import { Wedge } from '../../../primitive/wedge';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { Wedge } from 'mol-geo/primitive/wedge';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
 
 const t = Mat4.identity()
 const sVec = Vec3.zero()
diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts
similarity index 91%
rename from src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
rename to src/mol-repr/structure/visual/polymer-gap-cylinder.ts
index b4539c32463d5b4a6c0ab6801846d3e04f4769fe..389b494a229089a2c6da9c18299698de7b3528c3 100644
--- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts
+++ b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts
@@ -5,19 +5,20 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-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-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-util/parameter';
 import { LinkCylinderParams } from './util/link';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { CylinderProps } from 'mol-geo/primitive/cylinder';
+import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere';
+import { addFixedCountDashedCylinder } from 'mol-geo/geometry/mesh/builder/cylinder';
 
 const segmentCount = 10
 
diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts
similarity index 93%
rename from src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts
rename to src/mol-repr/structure/visual/polymer-trace-mesh.ts
index 390a757fec5cdfaef0998a16c0923b4f72381093..910f59b26e2d34ff85d078db1aeedb646ee1a65f 100644
--- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts
+++ b/src/mol-repr/structure/visual/polymer-trace-mesh.ts
@@ -5,17 +5,18 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { UnitsVisual, VisualUpdateState } from '..';
+import { UnitsVisual } from '../index';
+import { VisualUpdateState } from '../../util';
 import { RuntimeContext } from 'mol-task'
-import { Mesh } from '../../../geometry/mesh/mesh';
-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-theme/size';
-import { addSheet } from '../../../geometry/mesh/builder/sheet';
-import { addTube } from '../../../geometry/mesh/builder/tube';
 import { SelectParam, NumberParam, paramDefaultValues } from 'mol-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { addSheet } from 'mol-geo/geometry/mesh/builder/sheet';
+import { addTube } from 'mol-geo/geometry/mesh/builder/tube';
 
 export const PolymerTraceMeshParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions),
diff --git a/src/mol-geo/representation/structure/visual/util/common.ts b/src/mol-repr/structure/visual/util/common.ts
similarity index 78%
rename from src/mol-geo/representation/structure/visual/util/common.ts
rename to src/mol-repr/structure/visual/util/common.ts
index cadf7fef3acfa3d5e50d5ae02b2600809db40edf..33f226f22aafb4fecb3019379eea8fdf58f27858 100644
--- a/src/mol-geo/representation/structure/visual/util/common.ts
+++ b/src/mol-repr/structure/visual/util/common.ts
@@ -5,19 +5,17 @@
  */
 
 import { Unit, Structure } from 'mol-model/structure';
-import { LocationIterator } from '../../../../util/location-iterator';
-import { Mesh } from '../../../../geometry/mesh/mesh';
-import { StructureProps } from '../..';
+import { StructureProps } from '../../index';
 import { createMeshRenderObject, createPointsRenderObject, createLinesRenderObject, createDirectVolumeRenderObject } from 'mol-gl/render-object';
 import { RuntimeContext } from 'mol-task';
-import { TransformData, createIdentityTransform, createTransform } from '../../../../geometry/transform-data';
-import { Points } from '../../../../geometry/points/points';
-import { createRenderableState } from '../../../../geometry/geometry';
 import { Mat4 } from 'mol-math/linear-algebra';
-import { Lines } from '../../../../geometry/lines/lines';
-import { DirectVolume } from '../../../../geometry/direct-volume/direct-volume';
-import { SizeProps } from 'mol-geo/geometry/size-data';
-import { ColorProps } from 'mol-geo/geometry/color-data';
+import { TransformData, createTransform, createIdentityTransform } from 'mol-geo/geometry/transform-data';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { createRenderableState } from 'mol-geo/geometry/geometry';
+import { Points } from 'mol-geo/geometry/points/points';
+import { Lines } from 'mol-geo/geometry/lines/lines';
+import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume';
 
 export function createUnitsTransform({ units }: Unit.SymmetryGroup, transformData?: TransformData) {
     const unitCount = units.length
@@ -47,21 +45,6 @@ export function includesUnitKind(unitKinds: UnitKind[], unit: Unit) {
     return false
 }
 
-export function sizeChanged(oldProps: SizeProps, newProps: SizeProps) {
-    return (
-        oldProps.sizeTheme !== newProps.sizeTheme ||
-        oldProps.sizeValue !== newProps.sizeValue ||
-        oldProps.sizeFactor !== newProps.sizeFactor
-    )
-}
-
-export function colorChanged(oldProps: ColorProps, newProps: ColorProps) {
-    return (
-        oldProps.colorTheme !== newProps.colorTheme ||
-        oldProps.colorValue !== newProps.colorValue
-    )
-}
-
 // mesh
 
 type StructureMeshProps = Mesh.Props & StructureProps
diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-repr/structure/visual/util/element.ts
similarity index 90%
rename from src/mol-geo/representation/structure/visual/util/element.ts
rename to src/mol-repr/structure/visual/util/element.ts
index dfd6cf68c30a4725eec1f2c301c0dd249cbb8b57..4c1362033225ef4a8c9d1cbbacfe465d08bfda6e 100644
--- a/src/mol-geo/representation/structure/visual/util/element.ts
+++ b/src/mol-repr/structure/visual/util/element.ts
@@ -7,15 +7,15 @@
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Unit, StructureElement, Structure } from 'mol-model/structure';
 import { RuntimeContext } from 'mol-task';
-import { sphereVertexCount } from '../../../../primitive/sphere';
-import { Mesh } from '../../../../geometry/mesh/mesh';
-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-theme/size';
-import { LocationIterator } from '../../../../util/location-iterator';
-import { addSphere } from '../../../../geometry/mesh/builder/sphere';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { sphereVertexCount } from 'mol-geo/primitive/sphere';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
 
 export interface ElementSphereMeshProps {
     sizeTheme: SizeThemeName,
diff --git a/src/mol-geo/representation/structure/visual/util/gaussian.ts b/src/mol-repr/structure/visual/util/gaussian.ts
similarity index 100%
rename from src/mol-geo/representation/structure/visual/util/gaussian.ts
rename to src/mol-repr/structure/visual/util/gaussian.ts
diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-repr/structure/visual/util/link.ts
similarity index 95%
rename from src/mol-geo/representation/structure/visual/util/link.ts
rename to src/mol-repr/structure/visual/util/link.ts
index a5aa876861ec1c9ec4774c84a220274945f9c41a..53d9688bcbd168100046207df44a5c80160a2c4b 100644
--- a/src/mol-geo/representation/structure/visual/util/link.ts
+++ b/src/mol-repr/structure/visual/util/link.ts
@@ -6,15 +6,15 @@
 
 import { Vec3 } from 'mol-math/linear-algebra';
 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-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-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
+import { CylinderProps } from 'mol-geo/primitive/cylinder';
+import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from 'mol-geo/geometry/mesh/builder/cylinder';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
 
 export const LinkCylinderParams = {
     sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions),
diff --git a/src/mol-geo/representation/structure/visual/util/nucleotide.ts b/src/mol-repr/structure/visual/util/nucleotide.ts
similarity index 96%
rename from src/mol-geo/representation/structure/visual/util/nucleotide.ts
rename to src/mol-repr/structure/visual/util/nucleotide.ts
index de9e17a157236fd056b208724b428ebfc81f1a79..2ce7b7cb97e55d11c9d6c4f2f500590ed3283206 100644
--- a/src/mol-geo/representation/structure/visual/util/nucleotide.ts
+++ b/src/mol-repr/structure/visual/util/nucleotide.ts
@@ -5,11 +5,11 @@
  */
 
 import { Unit, StructureElement } from 'mol-model/structure';
-import { LocationIterator } from '../../../../util/location-iterator';
 import { getNucleotideElements } from 'mol-model/structure/structure/util/nucleotide';
-import { PickingId } from '../../../../geometry/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { OrderedSet, Interval } from 'mol-data/int';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
 
 export namespace NucleotideLocationIterator {
     export function fromGroup(group: Unit.SymmetryGroup): LocationIterator {
diff --git a/src/mol-geo/representation/structure/visual/util/polymer.ts b/src/mol-repr/structure/visual/util/polymer.ts
similarity index 97%
rename from src/mol-geo/representation/structure/visual/util/polymer.ts
rename to src/mol-repr/structure/visual/util/polymer.ts
index a2739dfa392c350ee5a695eead128e21142fcc03..80ff883ab70a95da86bf43de69a4f738a96e73a0 100644
--- a/src/mol-geo/representation/structure/visual/util/polymer.ts
+++ b/src/mol-repr/structure/visual/util/polymer.ts
@@ -6,10 +6,10 @@
 
 import { Unit, ElementIndex, StructureElement, Link } from 'mol-model/structure';
 import SortedRanges from 'mol-data/int/sorted-ranges';
-import { LocationIterator } from '../../../../util/location-iterator';
-import { PickingId } from '../../../../geometry/picking';
 import { OrderedSet, Interval } from 'mol-data/int';
 import { EmptyLoci, Loci } from 'mol-model/loci';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { PickingId } from 'mol-geo/geometry/picking';
 
 export * from './polymer/backbone-iterator'
 export * from './polymer/gap-iterator'
diff --git a/src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts b/src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts
similarity index 100%
rename from src/mol-geo/representation/structure/visual/util/polymer/backbone-iterator.ts
rename to src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts
diff --git a/src/mol-geo/representation/structure/visual/util/polymer/curve-segment.ts b/src/mol-repr/structure/visual/util/polymer/curve-segment.ts
similarity index 100%
rename from src/mol-geo/representation/structure/visual/util/polymer/curve-segment.ts
rename to src/mol-repr/structure/visual/util/polymer/curve-segment.ts
diff --git a/src/mol-geo/representation/structure/visual/util/polymer/gap-iterator.ts b/src/mol-repr/structure/visual/util/polymer/gap-iterator.ts
similarity index 100%
rename from src/mol-geo/representation/structure/visual/util/polymer/gap-iterator.ts
rename to src/mol-repr/structure/visual/util/polymer/gap-iterator.ts
diff --git a/src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts
similarity index 100%
rename from src/mol-geo/representation/structure/visual/util/polymer/trace-iterator.ts
rename to src/mol-repr/structure/visual/util/polymer/trace-iterator.ts
diff --git a/src/mol-geo/representation/util.ts b/src/mol-repr/util.ts
similarity index 67%
rename from src/mol-geo/representation/util.ts
rename to src/mol-repr/util.ts
index c8a83cf50beb2a7186c793b003a97bf10f03f844..792e9ff05be9e3331d77b8323948daba894e4916 100644
--- a/src/mol-geo/representation/util.ts
+++ b/src/mol-repr/util.ts
@@ -6,7 +6,49 @@
 
 import { defaults } from 'mol-util';
 import { Structure } from 'mol-model/structure';
-import { VisualQuality } from '../geometry/geometry';
+import { VisualQuality } from 'mol-geo/geometry/geometry';
+import { SizeProps } from 'mol-geo/geometry/size-data';
+import { ColorProps } from 'mol-geo/geometry/color-data';
+
+export interface VisualUpdateState {
+    updateTransform: boolean
+    updateColor: boolean
+    updateSize: boolean
+    createGeometry: boolean
+}
+export namespace VisualUpdateState {
+    export function create(): VisualUpdateState {
+        return {
+            updateTransform: false,
+            updateColor: false,
+            updateSize: false,
+            createGeometry: false
+        }
+    }
+    export function reset(state: VisualUpdateState) {
+        state.updateTransform = false
+        state.updateColor = false
+        state.updateSize = false
+        state.createGeometry = false
+    }
+}
+
+export function sizeChanged(oldProps: SizeProps, newProps: SizeProps) {
+    return (
+        oldProps.sizeTheme !== newProps.sizeTheme ||
+        oldProps.sizeValue !== newProps.sizeValue ||
+        oldProps.sizeFactor !== newProps.sizeFactor
+    )
+}
+
+export function colorChanged(oldProps: ColorProps, newProps: ColorProps) {
+    return (
+        oldProps.colorTheme !== newProps.colorTheme ||
+        oldProps.colorValue !== newProps.colorValue
+    )
+}
+
+//
 
 export interface QualityProps {
     quality: VisualQuality
diff --git a/src/mol-geo/representation/volume/direct-volume.ts b/src/mol-repr/volume/direct-volume.ts
similarity index 96%
rename from src/mol-geo/representation/volume/direct-volume.ts
rename to src/mol-repr/volume/direct-volume.ts
index 0654ab5304a192cf694864cd52264244f7ce3b18..5ec65ef71512ba9a5d0f93c7abaeb4dfad9f8809 100644
--- a/src/mol-geo/representation/volume/direct-volume.ts
+++ b/src/mol-repr/volume/direct-volume.ts
@@ -6,14 +6,10 @@
 
 import { VolumeData } from 'mol-model/volume'
 import { RuntimeContext } from 'mol-task'
-import { VolumeVisual, VolumeRepresentation } from '.';
+import { VolumeVisual, VolumeRepresentation } from './index';
 import { DirectVolumeRenderObject, createDirectVolumeRenderObject } from 'mol-gl/render-object';
-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-util/parameter';
-import { DirectVolume } from '../../geometry/direct-volume/direct-volume';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { Box3D } from 'mol-math/geometry';
 import { WebGLContext } from 'mol-gl/webgl/context';
@@ -21,6 +17,10 @@ import { createTexture } from 'mol-gl/webgl/texture';
 import { LocationIterator } from 'mol-geo/util/location-iterator';
 import { NullLocation } from 'mol-model/location';
 import { createIdentityTransform } from 'mol-geo/geometry/transform-data';
+import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume';
+import { Geometry, createRenderableState, updateRenderableState } from 'mol-geo/geometry/geometry';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction } from 'mol-geo/geometry/marker-data';
 
 function getBoundingBox(gridDimension: Vec3, transform: Mat4) {
     const bbox = Box3D.empty()
diff --git a/src/mol-repr/volume/index.ts b/src/mol-repr/volume/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..49f6a31cbc4a82bb0b9a40027db320eef005075a
--- /dev/null
+++ b/src/mol-repr/volume/index.ts
@@ -0,0 +1,191 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Task, RuntimeContext } from 'mol-task'
+import { RepresentationProps, Representation, Visual } from '..';
+import { VolumeData, VolumeIsoValue } from 'mol-model/volume';
+import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci';
+import { paramDefaultValues, RangeParam } from 'mol-util/parameter';
+import { Geometry, updateRenderableState } from 'mol-geo/geometry/geometry';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction, applyMarkerAction } from 'mol-geo/geometry/marker-data';
+import { DirectVolumeRenderObject, PointsRenderObject, LinesRenderObject, MeshRenderObject } from 'mol-gl/render-object';
+import { Interval } from 'mol-data/int';
+import { RenderableValues } from 'mol-gl/renderable/schema';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { NullLocation } from 'mol-model/location';
+import { VisualUpdateState } from 'mol-repr/util';
+import { ValueCell } from 'mol-util';
+
+export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { }
+
+type VolumeRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject
+
+interface VolumeVisualBuilder<P extends VolumeProps, G extends Geometry> {
+    defaultProps: P
+    createGeometry(ctx: RuntimeContext, volumeData: VolumeData, props: P, geometry?: G): Promise<G>
+    getLoci(pickingId: PickingId, id: number): Loci
+    mark(loci: Loci, apply: (interval: Interval) => boolean): boolean
+    setUpdateState(state: VisualUpdateState, newProps: P, currentProps: P): void
+}
+
+interface VolumeVisualGeometryBuilder<P extends VolumeProps, G extends Geometry> extends VolumeVisualBuilder<P, G> {
+    createRenderObject(ctx: RuntimeContext, geometry: G, locationIt: LocationIterator, currentProps: P): Promise<VolumeRenderObject>
+    updateValues(values: RenderableValues, newProps: P): void
+}
+
+export function VolumeVisual<P extends VolumeProps>(builder: VolumeVisualGeometryBuilder<P, Geometry>) {
+    const { defaultProps, createGeometry, getLoci, mark, setUpdateState } = builder
+    const { createRenderObject, updateValues } = builder
+    const updateState = VisualUpdateState.create()
+
+    let currentProps: P
+    let renderObject: VolumeRenderObject | undefined
+    let currentVolume: VolumeData
+    let geometry: Geometry
+    let locationIt: LocationIterator
+
+    async function create(ctx: RuntimeContext, volume: VolumeData, props: Partial<VolumeProps> = {}) {
+        currentProps = Object.assign({}, defaultProps, props)
+        if (props.isoValueRelative) {
+            currentProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
+            console.log('create props.isoValueRelative', props.isoValueRelative, currentProps.isoValueAbsolute, currentVolume.dataStats)
+        }
+
+        geometry = await createGeometry(ctx, volume, currentProps, geometry)
+        locationIt = LocationIterator(1, 1, () => NullLocation)
+        renderObject = await createRenderObject(ctx, geometry, locationIt, currentProps)
+    }
+
+    async function update(ctx: RuntimeContext, props: Partial<VolumeProps> = {}) {
+        if (!renderObject) return
+        const newProps = Object.assign({}, currentProps, props)
+
+        if (props.isoValueRelative) {
+            newProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
+            console.log('update props.isoValueRelative', props.isoValueRelative, newProps.isoValueAbsolute, currentVolume.dataStats)
+        }
+
+        VisualUpdateState.reset(updateState)
+        setUpdateState(updateState, newProps, currentProps)
+
+        if (updateState.createGeometry) {
+            geometry = await createGeometry(ctx, currentVolume, currentProps, geometry)
+            ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(geometry))
+        }
+
+        updateValues(renderObject.values, newProps)
+        updateRenderableState(renderObject.state, newProps)
+
+        currentProps = newProps
+    }
+
+    return {
+        get renderObject () { return renderObject },
+        async createOrUpdate(ctx: RuntimeContext, props: Partial<VolumeProps> = {}, volume?: VolumeData) {
+            if (!volume && !currentVolume) {
+                throw new Error('missing volume')
+            } else if (volume && (!currentVolume || !renderObject)) {
+                currentVolume = volume
+                await create(ctx, volume, props)
+            } else if (volume && volume !== currentVolume) {
+                currentVolume = volume
+                await create(ctx, volume, props)
+            } else {
+                await update(ctx, props)
+            }
+
+            currentProps = Object.assign({}, defaultProps, props)
+        },
+        getLoci(pickingId: PickingId) {
+            return renderObject ? getLoci(pickingId, renderObject.id) : EmptyLoci
+        },
+        mark(loci: Loci, action: MarkerAction) {
+            if (!renderObject) return false
+            const { tMarker } = renderObject.values
+            const { groupCount, instanceCount } = locationIt
+
+            function apply(interval: Interval) {
+                const start = Interval.start(interval)
+                const end = Interval.end(interval)
+                return applyMarkerAction(tMarker.ref.value.array, start, end, action)
+            }
+
+            let changed = false
+            if (isEveryLoci(loci)) {
+                changed = apply(Interval.ofBounds(0, groupCount * instanceCount))
+            } else {
+                changed = mark(loci, apply)
+            }
+            if (changed) {
+                ValueCell.update(tMarker, tMarker.ref.value)
+            }
+            return changed
+        },
+        destroy() {
+            // TODO
+            renderObject = undefined
+        }
+    }
+}
+
+export interface VolumeRepresentation<P extends RepresentationProps = {}> extends Representation<VolumeData, P> { }
+
+export const VolumeParams = {
+    ...Geometry.Params,
+    isoValueAbsolute: RangeParam('Iso Value Absolute', '', 0.22, -1, 1, 0.01),
+    isoValueRelative: RangeParam('Iso Value Relative', '', 2, -10, 10, 0.1),
+}
+export const DefaultVolumeProps = paramDefaultValues(VolumeParams)
+export type VolumeProps = typeof DefaultVolumeProps
+
+export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeData: VolumeData) => VolumeVisual<P>): VolumeRepresentation<P> {
+    let visual: VolumeVisual<any>
+    let _props: P
+    let busy = false
+
+    function createOrUpdate(props: Partial<P> = {}, volumeData?: VolumeData) {
+        _props = Object.assign({}, DefaultVolumeProps, _props, props)
+        return Task.create('VolumeRepresentation.create', async ctx => {
+            // TODO queue it somehow
+            if (busy) return
+
+            if (!visual && !volumeData) {
+                throw new Error('volumeData missing')
+            } else if (volumeData && !visual) {
+                busy = true
+                visual = visualCtor(volumeData)
+                await visual.createOrUpdate(ctx, props, volumeData)
+                busy = false
+            } else {
+                busy = true
+                await visual.createOrUpdate(ctx, props, volumeData)
+                busy = false
+            }
+        });
+    }
+
+    return {
+        label: 'Volume',
+        params: VolumeParams,
+        get renderObjects() {
+            return visual && visual.renderObject ? [ visual.renderObject ] : []
+        },
+        get props () { return _props },
+        createOrUpdate,
+        getLoci(pickingId: PickingId) {
+            // TODO
+            return EmptyLoci
+        },
+        mark(loci: Loci, action: MarkerAction) {
+            // TODO
+            return false
+        },
+        destroy() {
+            // TODO
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mol-repr/volume/isosurface-mesh.ts b/src/mol-repr/volume/isosurface-mesh.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0dd1b600d245b7f94de9f147d4b17f471b8f8033
--- /dev/null
+++ b/src/mol-repr/volume/isosurface-mesh.ts
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { VolumeData } from 'mol-model/volume'
+import { RuntimeContext } from 'mol-task'
+import { VolumeVisual, VolumeRepresentation } from './index';
+import { createMeshRenderObject } from 'mol-gl/render-object';
+import { Loci, EmptyLoci } from 'mol-model/loci';
+import { paramDefaultValues, RangeParam } from 'mol-util/parameter';
+import { Mesh } from 'mol-geo/geometry/mesh/mesh';
+import { computeMarchingCubesMesh } from 'mol-geo/util/marching-cubes/algorithm';
+import { LocationIterator } from 'mol-geo/util/location-iterator';
+import { createIdentityTransform } from 'mol-geo/geometry/transform-data';
+import { createRenderableState } from 'mol-geo/geometry/geometry';
+import { PickingId } from 'mol-geo/geometry/picking';
+import { MarkerAction } from 'mol-geo/geometry/marker-data';
+import { VisualUpdateState } from 'mol-repr/util';
+
+interface VolumeIsosurfaceProps {
+    isoValueAbsolute: number
+}
+
+export async function createVolumeIsosurface(ctx: RuntimeContext, volume: VolumeData, props: VolumeIsosurfaceProps, mesh?: Mesh) {
+    ctx.update({ message: 'Marching cubes...' });
+
+    const surface = await computeMarchingCubesMesh({
+        isoLevel: props.isoValueAbsolute,
+        scalarField: volume.data
+    }, mesh).runAsChild(ctx);
+
+    const transform = VolumeData.getGridToCartesianTransform(volume);
+    ctx.update({ message: 'Transforming mesh...' });
+    Mesh.transformImmediate(surface, transform);
+    Mesh.computeNormalsImmediate(surface)
+
+    return surface;
+}
+
+export const IsosurfaceParams = {
+    ...Mesh.Params,
+    isoValueAbsolute: RangeParam('Iso Value Absolute', '', 0.22, -1, 1, 0.01),
+    isoValueRelative: RangeParam('Iso Value Relative', '', 2, -10, 10, 0.1),
+}
+export const DefaultIsosurfaceProps = paramDefaultValues(IsosurfaceParams)
+export type IsosurfaceProps = typeof DefaultIsosurfaceProps
+
+export function IsosurfaceVisual():  VolumeVisual<IsosurfaceProps> {
+    return VolumeVisual<IsosurfaceProps>({
+        defaultProps: DefaultIsosurfaceProps,
+        createGeometry: createVolumeIsosurface,
+        getLoci: () => EmptyLoci,
+        mark: () => false,
+        setUpdateState: (state: VisualUpdateState, newProps: IsosurfaceProps, currentProps: IsosurfaceProps) => {
+            if (newProps.isoValueAbsolute !== currentProps.isoValueAbsolute) state.createGeometry = true
+        },
+        createRenderObject: async (ctx: RuntimeContext, geometry: Mesh, locationIt: LocationIterator, props: IsosurfaceProps) => {
+            const transform = createIdentityTransform()
+            const values = await Mesh.createValues(ctx, geometry, transform, locationIt, props)
+            const state = createRenderableState(props)
+            return createMeshRenderObject(values, state)
+        },
+        updateValues: Mesh.updateValues
+    })
+}
+
+export function IsosurfaceRepresentation(): VolumeRepresentation<IsosurfaceProps> {
+    let currentProps: IsosurfaceProps
+    const volumeRepr = VolumeRepresentation(IsosurfaceVisual)
+    return {
+        label: 'Isosurface',
+        params: IsosurfaceParams,
+        get renderObjects() {
+            return [ ...volumeRepr.renderObjects ]
+        },
+        get props() {
+            return { ...volumeRepr.props }
+        },
+        createOrUpdate: (props: Partial<IsosurfaceProps> = {}, volume?: VolumeData) => {
+            currentProps = Object.assign({}, DefaultIsosurfaceProps, currentProps, props)
+            return volumeRepr.createOrUpdate(currentProps, volume)
+        },
+        getLoci: (pickingId: PickingId) => {
+            return volumeRepr.getLoci(pickingId)
+        },
+        mark: (loci: Loci, action: MarkerAction) => {
+            return volumeRepr.mark(loci, action)
+        },
+        destroy() {
+            volumeRepr.destroy()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts
index 001b497b62913a702ed8e78df347a929006d922f..c11848731cdae4a30529c7d2e62a9ed272b8cc26 100644
--- a/src/mol-theme/color.ts
+++ b/src/mol-theme/color.ts
@@ -22,6 +22,7 @@ import { ResidueNameColorTheme } from './color/residue-name';
 import { SequenceIdColorTheme } from './color/sequence-id';
 import { SecondaryStructureColorTheme } from './color/secondary-structure';
 import { MoleculeTypeColorTheme } from './color/molecule-type';
+import { PolymerIndexColorTheme } from './color/polymer-index';
 
 export type LocationColor = (location: Location, isSecondary: boolean) => Color
 
@@ -59,6 +60,7 @@ export function ColorTheme(props: ColorThemeProps): ColorTheme {
         case 'element-index': return ElementIndexColorTheme(props)
         case 'element-symbol': return ElementSymbolColorTheme(props)
         case 'molecule-type': return MoleculeTypeColorTheme(props)
+        case 'polymer-index': return PolymerIndexColorTheme(props)
         case 'residue-name': return ResidueNameColorTheme(props)
         case 'secondary-structure': return SecondaryStructureColorTheme(props)
         case 'sequence-id': return SequenceIdColorTheme(props)
@@ -87,6 +89,7 @@ export const ColorThemeInfo = {
     'element-index': {},
     'element-symbol': {},
     'molecule-type': {},
+    'polymer-index': {},
     'residue-name': {},
     'secondary-structure': {},
     'sequence-id': {},
diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..891b17300f72f94ab19e1c1883e19c303f9d0659
--- /dev/null
+++ b/src/mol-theme/color/polymer-index.ts
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { ColorScale, Color } from 'mol-util/color';
+import { Location } from 'mol-model/location';
+import { StructureElement, Link } from 'mol-model/structure';
+import { ColorTheme, ColorThemeProps, LocationColor } from '../color';
+
+const DefaultColor = Color(0xCCCCCC)
+const Description = 'Gives every polymer a unique color based on the position (index) of the polymer in the list of polymers in the structure.'
+
+export function PolymerIndexColorTheme(props: ColorThemeProps): ColorTheme {
+    let color: LocationColor
+    let scale: ColorScale | undefined = undefined
+
+    if (props.structure) {
+        const { units } = props.structure
+        let polymerCount = 0
+        for (let i = 0, il = units.length; i <il; ++i) {
+            if (units[i].polymerElements.length > 0) ++polymerCount
+        }
+        scale = ColorScale.create({ domain: [ 0, polymerCount - 1 ] })
+        const unitIdColor = new Map<number, Color>()
+        for (let i = 0, j = 0, il = units.length; i <il; ++i) {
+            if (units[i].polymerElements.length > 0) {
+                unitIdColor.set(units[i].id, scale.color(j))
+                ++j
+            }
+        }
+
+        color = (location: Location): Color => {
+            let color: Color | undefined
+            if (StructureElement.isLocation(location)) {
+                color = unitIdColor.get(location.unit.id)
+            } else if (Link.isLocation(location)) {
+                color = unitIdColor.get(location.aUnit.id)
+            }
+            return color !== undefined ? color : DefaultColor
+        }
+    } else {
+        color = () => DefaultColor
+    }
+
+    return {
+        granularity: 'instance',
+        color,
+        description: Description,
+        legend: scale ? scale.legend : undefined
+    }
+}
\ No newline at end of file
diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts
index 92d4f53bbe552f2017b873dd7778ee0d6621e3e2..3e4fed18b986e43f85fa9c076d9d765695f73494 100644
--- a/src/mol-theme/color/unit-index.ts
+++ b/src/mol-theme/color/unit-index.ts
@@ -21,7 +21,7 @@ export function UnitIndexColorTheme(props: ColorThemeProps): ColorTheme {
         scale = ColorScale.create({ domain: [ 0, units.length - 1 ] })
         const unitIdColor = new Map<number, Color>()
         for (let i = 0, il = units.length; i <il; ++i) {
-            unitIdColor.set(units[i].id, scale.color(units[i].id))
+            unitIdColor.set(units[i].id, scale.color(i))
         }
 
         color = (location: Location): Color => {
diff --git a/tsconfig.json b/tsconfig.json
index e82eb6af14db2e816708e40e12621ac9d93074dd..acb69eee3adf78ff9690fd1c7837fddae3c8c7a9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,17 +17,18 @@
             "mol-app": ["./mol-app"],
             "mol-data": ["./mol-data", "./mol-data/index.ts"],
             "mol-geo": ["./mol-geo"],
-            "mol-theme": ["./mol-theme"],
             "mol-gl": ["./mol-gl"],
             "mol-io": ["./mol-io"],
             "mol-math": ["./mol-math"],
             "mol-model": ["./mol-model"],
             "mol-model-props": ["./mol-model-props", "./mol-model-props/index.ts"],
             "mol-ql": ["./mol-ql"],
+            "mol-repr": ["./mol-repr"],
             "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-theme": ["./mol-theme"],
             "mol-util": ["./mol-util", "./mol-util/index.ts"],
             "mol-canvas3d": ["./mol-view"]
         }