diff --git a/examples/webgl/README.md b/examples/webgl/README.md
new file mode 100644
index 0000000000..9fd5836b7c
--- /dev/null
+++ b/examples/webgl/README.md
@@ -0,0 +1,12 @@
+# webgl
+
+[Live demo](http://demo.thi.ng/umbrella/hiccup-dom/webgl/)
+
+```
+git clone https://github.com/thi-ng/umbrella.git
+cd umbrella/examples/webgl
+yarn install
+yarn dev
+```
+
+Once webpack has completed building, refresh your browser...
diff --git a/examples/webgl/index.html b/examples/webgl/index.html
new file mode 100644
index 0000000000..ffa71aacd8
--- /dev/null
+++ b/examples/webgl/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/webgl/package.json b/examples/webgl/package.json
new file mode 100644
index 0000000000..b9dc428b3a
--- /dev/null
+++ b/examples/webgl/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "webgl",
+ "version": "0.0.1",
+ "repository": "https://github.com/thi-ng/umbrella",
+ "author": "Karsten Schmidt ",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "yarn clean && webpack",
+ "clean": "rm -rf bundle.*",
+ "dev": "open index.html && webpack -w"
+ },
+ "devDependencies": {
+ "ts-loader": "^3.3.1",
+ "typescript": "^2.7.1",
+ "webpack": "^3.10.0"
+ },
+ "dependencies": {
+ "@thi.ng/hiccup-dom": "^0.1.1"
+ }
+}
\ No newline at end of file
diff --git a/examples/webgl/src/index.ts b/examples/webgl/src/index.ts
new file mode 100644
index 0000000000..0e810ad4b5
--- /dev/null
+++ b/examples/webgl/src/index.ts
@@ -0,0 +1,44 @@
+import { start } from "@thi.ng/hiccup-dom";
+
+let frame = 0;
+
+// reusable GL canvas component
+const glcanvas = (init, update, attribs) => {
+ let gl: WebGLRenderingContext;
+ return [{
+ init(el: HTMLCanvasElement) {
+ gl = el.getContext("webgl");
+ init(gl);
+ },
+ render() {
+ gl && update(gl);
+ return ["canvas", attribs]
+ }
+ }];
+};
+
+// canvas init hook
+const initGL = (_: WebGLRenderingContext) => {
+ // init here
+};
+
+// canvas render hook
+const updateGL = (offset) =>
+ (gl: WebGLRenderingContext) => {
+ frame++;
+ const f = offset + frame * 0.01;
+ const red = Math.sin(f) * 0.5 + 0.5;
+ const green = Math.sin(f + Math.PI * 1 / 3) * 0.5 + 0.5;
+ const blue = Math.sin(f + Math.PI * 2 / 3) * 0.5 + 0.5;
+ gl.clearColor(red, green, blue, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ };
+
+start(
+ document.getElementById("app"),
+ // instantiate multiple canvases
+ ["div",
+ glcanvas(initGL, updateGL(0), { width: 100, height: 100 }),
+ glcanvas(initGL, updateGL(200), { width: 100, height: 100 }),
+ glcanvas(initGL, updateGL(400), { width: 100, height: 100 })]
+);
diff --git a/examples/webgl/tsconfig.json b/examples/webgl/tsconfig.json
new file mode 100644
index 0000000000..bd6481a5a6
--- /dev/null
+++ b/examples/webgl/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "."
+ },
+ "include": [
+ "./src/**/*.ts"
+ ]
+}
diff --git a/examples/webgl/webpack.config.js b/examples/webgl/webpack.config.js
new file mode 100644
index 0000000000..26efe6fb12
--- /dev/null
+++ b/examples/webgl/webpack.config.js
@@ -0,0 +1,17 @@
+module.exports = {
+ entry: "./src/index.ts",
+ output: {
+ path: __dirname,
+ filename: "bundle.js"
+ },
+ resolve: {
+ extensions: [".ts", ".js"]
+ },
+ module: {
+ loaders: [{ test: /\.ts$/, loader: "ts-loader" }]
+ },
+ node: {
+ process: false,
+ setImmediate: false
+ }
+};