diff --git a/.travis.yml b/.travis.yml
index 127091b..086faf9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,6 +13,7 @@ matrix:
   include:
     - env: DESTINATION="OS=10.3,name=iPhone 7" SCHEME=Matrioska SDK="iphonesimulator10.3" COVERAGE=YES
       before_install:
+        - brew update && brew install swiftlint
         - gem install danger --no-ri --no-doc
         - gem install danger-swiftlint --no-ri --no-doc
       before_script:
diff --git a/Example/.swiftlint.yml b/Example/.swiftlint.yml
new file mode 100644
index 0000000..269072f
--- /dev/null
+++ b/Example/.swiftlint.yml
@@ -0,0 +1,23 @@
+disabled_rules:
+  - trailing_whitespace # seems like Xcode does this by default
+
+opt_in_rules:
+  - empty_count
+  - force_unwrapping
+  - private_outlet
+  - vertical_whitespace
+#  - missing_docs # broken
+  - closure_spacing
+  - conditional_returns_on_newline
+  - overridden_super_call
+  - redundant_nil_coalesing
+#  - switch_case_on_newline # broken
+  
+included:
+  - MatrioskaExample
+  
+excluded:
+  - Pods
+  - Example
+
+reporter: "xcode"
diff --git a/Example/MatrioskaExample.xcodeproj/project.pbxproj b/Example/MatrioskaExample.xcodeproj/project.pbxproj
index 9c76b8f..340f4ec 100644
--- a/Example/MatrioskaExample.xcodeproj/project.pbxproj
+++ b/Example/MatrioskaExample.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		21F6211E1E3147AF006C0DBE /* JSONReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F6211D1E3147AF006C0DBE /* JSONReader.swift */; };
+		21F621201E3147D5006C0DBE /* app_structure.json in Resources */ = {isa = PBXBuildFile; fileRef = 21F6211F1E3147D5006C0DBE /* app_structure.json */; };
+		21F621221E3155D1006C0DBE /* MatrioskaCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F621211E3155D1006C0DBE /* MatrioskaCodeViewController.swift */; };
 		3E97AAB4FE1D9B124FD14CAB /* Pods_MatrioskaExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0188753F69D4AFD24551958B /* Pods_MatrioskaExample.framework */; };
 		DE7C386A1E005E3C00A399A3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7C38691E005E3C00A399A3 /* AppDelegate.swift */; };
 		DE7C386C1E005E3C00A399A3 /* TileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE7C386B1E005E3C00A399A3 /* TileViewController.swift */; };
@@ -17,6 +20,9 @@
 /* Begin PBXFileReference section */
 		0188753F69D4AFD24551958B /* Pods_MatrioskaExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MatrioskaExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		10AE7CFAC2D2657BBA53BF57 /* Pods-MatrioskaExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MatrioskaExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MatrioskaExample/Pods-MatrioskaExample.debug.xcconfig"; sourceTree = "<group>"; };
+		21F6211D1E3147AF006C0DBE /* JSONReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONReader.swift; sourceTree = "<group>"; };
+		21F6211F1E3147D5006C0DBE /* app_structure.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = app_structure.json; sourceTree = "<group>"; };
+		21F621211E3155D1006C0DBE /* MatrioskaCodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatrioskaCodeViewController.swift; sourceTree = "<group>"; };
 		DE7C38661E005E3C00A399A3 /* MatrioskaExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MatrioskaExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		DE7C38691E005E3C00A399A3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		DE7C386B1E005E3C00A399A3 /* TileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileViewController.swift; sourceTree = "<group>"; };
@@ -68,11 +74,14 @@
 		DE7C38681E005E3C00A399A3 /* MatrioskaExample */ = {
 			isa = PBXGroup;
 			children = (
+				21F6211F1E3147D5006C0DBE /* app_structure.json */,
+				21F6211D1E3147AF006C0DBE /* JSONReader.swift */,
 				DE7C38691E005E3C00A399A3 /* AppDelegate.swift */,
 				DE7C386B1E005E3C00A399A3 /* TileViewController.swift */,
 				DE7C38701E005E3C00A399A3 /* Assets.xcassets */,
 				DE7C38721E005E3C00A399A3 /* LaunchScreen.storyboard */,
 				DE7C38751E005E3C00A399A3 /* Info.plist */,
+				21F621211E3155D1006C0DBE /* MatrioskaCodeViewController.swift */,
 			);
 			path = MatrioskaExample;
 			sourceTree = "<group>";
@@ -98,6 +107,7 @@
 				DE7C38641E005E3C00A399A3 /* Resources */,
 				4AE147B018A9543A80727648 /* [CP] Embed Pods Frameworks */,
 				AC908C2BE3E29B7037E5E673 /* [CP] Copy Pods Resources */,
+				21F621231E315F15006C0DBE /* swiftlint */,
 			);
 			buildRules = (
 			);
@@ -148,6 +158,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				DE7C38741E005E3C00A399A3 /* LaunchScreen.storyboard in Resources */,
+				21F621201E3147D5006C0DBE /* app_structure.json in Resources */,
 				DE7C38711E005E3C00A399A3 /* Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -155,6 +166,20 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
+		21F621231E315F15006C0DBE /* swiftlint */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = swiftlint;
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
+		};
 		4AE147B018A9543A80727648 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -208,7 +233,9 @@
 			buildActionMask = 2147483647;
 			files = (
 				DE7C386C1E005E3C00A399A3 /* TileViewController.swift in Sources */,
+				21F6211E1E3147AF006C0DBE /* JSONReader.swift in Sources */,
 				DE7C386A1E005E3C00A399A3 /* AppDelegate.swift in Sources */,
+				21F621221E3155D1006C0DBE /* MatrioskaCodeViewController.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Example/MatrioskaExample/AppDelegate.swift b/Example/MatrioskaExample/AppDelegate.swift
index 13479e0..f9842cb 100644
--- a/Example/MatrioskaExample/AppDelegate.swift
+++ b/Example/MatrioskaExample/AppDelegate.swift
@@ -14,72 +14,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 
     var window: UIWindow?
 
-    let rootComponent = ClusterLayout.tabBar(
-        children: [
-            blankComponent(
-                meta: ClusterLayout.TabConfig(title: "First", iconName: "tabIcon")
-            ),
-            blankComponent(
-                meta: ClusterLayout.TabConfig(title: "Second", iconName: "tabIcon")
-            ),
-            navComponent(child:
-                ClusterLayout.stack(
-                    children: [
-                        tileComponent(meta: TileConfig(text: "One", color: .red)),
-                        tileComponent(meta: TileConfig(text: "Two", color: .green)),
-                        ClusterLayout.stack(
-                            children: [
-                                tileComponent(meta: TileConfig(text: "A", color: .red)),
-                                tileComponent(meta: TileConfig(text: "B", color: .green)),
-                                tileComponent(meta: TileConfig(text: "C", color: .orange)),
-                                tileComponent(meta: TileConfig(text: "D", color: .yellow))
-                                ],
-                            meta: ClusterLayout.StackConfig(axis: .horizontal)
-                        ),
-                        tileComponent(meta: TileConfig(text: "Three", color: .orange)),
-                        tileComponent(meta: TileConfig(text: "Four", color: .yellow))
-                    ],
-                    meta: ZipMeta(ClusterLayout.TabConfig(title: "Third", iconName: "tabIcon"))
-                )
-            ),
-            blankComponent(
-                meta: ClusterLayout.TabConfig(title: "Fourth", iconName: "tabIcon")
-            ),
-            blankComponent(
-                meta: ClusterLayout.TabConfig(title: "Fifth", iconName: "tabIcon")
-            )
-        ],
-        meta: ClusterLayout.TabBarConfig(selectedIndex: 2)
-    )
-
     func application(_ application: UIApplication,
                      didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
         
         window = UIWindow(frame: UIScreen.main.bounds)
-        window?.rootViewController = rootComponent.viewController()
-        window?.makeKeyAndVisible()
+        
+        let factory = JSONFactory()
+        
+        let tabBarBuilder: JSONFactory.ClusterBuilder = { (children, meta) in
+            ClusterLayout.tabBar(children: children, meta: meta)
+        }
+        
+        let stackBuilder: JSONFactory.ClusterBuilder = { (children, meta) in
+            ClusterLayout.stack(children: children, meta: meta)
+        }
+        
+        let navigationBuilder: JSONFactory.WrapperBuilder = { (child, meta) in
+            Component.wrapper(viewBuilder: { (child, meta) in
+                guard let vc = child.viewController() else {
+                    return nil
+                }
+                return UINavigationController(rootViewController: vc)
+            }, child: child, meta: meta)
+        }
+        
+        let tileBuilder: JSONFactory.SingleBuilder = { (meta) in
+            Component.single(viewBuilder: { (meta) -> UIViewController? in
+                    TileViewController.init(meta: TileConfig.materialize(meta))
+                }, meta: meta)
+        }
+        
+        let matrioskaCodeBuilder: JSONFactory.SingleBuilder = { (meta) in
+            Component.single(viewBuilder: {_ in 
+                return MatrioskaCodeViewController()
+            }, meta: meta)
+        }
+        
+        factory.register(builder: tabBarBuilder, forType: "tabbar")
+        factory.register(builder: stackBuilder, forType: "stack")
+        factory.register(builder: navigationBuilder, forType: "navigation")
+        factory.register(builder: tileBuilder, forType: "tile")
+        factory.register(builder: matrioskaCodeBuilder, forType: "matrioska")
+        
+        do {
+            if let json = try JSONReader.jsonObject(from: "app_structure") {
+                
+                let rootComponent = try factory.makeComponent(json: json)
+                window?.rootViewController = rootComponent?.viewController()
+                window?.makeKeyAndVisible()
+            }
+            
+        } catch {
+            assert(false, "JSON could not be parsed")
+        }
         
         return true
     }
 }
-
-private func navComponent(child: Component) -> Component {
-    let viewBuilder: Component.WrapperViewBuilder = { (child, meta) -> UIViewController? in
-        return child.viewController().map { UINavigationController(rootViewController: $0) }
-    }
-    
-    return Component.wrapper(viewBuilder: viewBuilder, child: child, meta: child.meta)
-}
-
-private func blankComponent(meta: ComponentMeta?) -> Component {
-    let viewBuilder: Component.SingleViewBuilder = { (meta) in
-        let vc = UIViewController()
-        vc.view.backgroundColor = .white
-        return vc
-    }
-    return Component.single(viewBuilder: viewBuilder, meta: meta)
-}
-
-private func tileComponent(meta: TileConfig) -> Component {
-    return Component.single(viewBuilder: TileViewController.init(meta:), meta: meta)
-}
diff --git a/Example/MatrioskaExample/Assets.xcassets/home.imageset/Contents.json b/Example/MatrioskaExample/Assets.xcassets/home.imageset/Contents.json
new file mode 100644
index 0000000..47149c6
--- /dev/null
+++ b/Example/MatrioskaExample/Assets.xcassets/home.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "home.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/Example/MatrioskaExample/Assets.xcassets/home.imageset/home.png b/Example/MatrioskaExample/Assets.xcassets/home.imageset/home.png
new file mode 100644
index 0000000..9e57a60
Binary files /dev/null and b/Example/MatrioskaExample/Assets.xcassets/home.imageset/home.png differ
diff --git a/Example/MatrioskaExample/Assets.xcassets/list.imageset/Contents.json b/Example/MatrioskaExample/Assets.xcassets/list.imageset/Contents.json
new file mode 100644
index 0000000..e0478e1
--- /dev/null
+++ b/Example/MatrioskaExample/Assets.xcassets/list.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "list.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/Example/MatrioskaExample/Assets.xcassets/list.imageset/list.png b/Example/MatrioskaExample/Assets.xcassets/list.imageset/list.png
new file mode 100644
index 0000000..bcff29b
Binary files /dev/null and b/Example/MatrioskaExample/Assets.xcassets/list.imageset/list.png differ
diff --git a/Example/MatrioskaExample/JSONReader.swift b/Example/MatrioskaExample/JSONReader.swift
new file mode 100644
index 0000000..dbb149b
--- /dev/null
+++ b/Example/MatrioskaExample/JSONReader.swift
@@ -0,0 +1,42 @@
+//
+//  JSONReader.swift
+//  Matrioska
+//
+//  Created by Andreas Thenn on 12/01/2017.
+//  Copyright © 2017 runtastic. All rights reserved.
+//
+
+import Foundation
+@testable import Matrioska
+
+/// A JSONReader used to convert to JSONObject
+final class JSONReader {
+    
+    /// Serializes from a given JSON Data into JSONObject
+    ///
+    /// - Parameter data: the Data object used in serialization
+    /// - Returns: an optional serialized JSONObject
+    /// - Throws: throws an error in case of failure or invalid JSON data
+    class func jsonObject(from data: Data) throws -> JSONObject? {
+        let json = try JSONSerialization.jsonObject(with: data) as? JSONObject
+        
+        return json
+    }
+
+    /// Serializes from a given JSON file into JSONObject
+    ///
+    /// - Parameters:
+    ///   - jsonFilename: the file name
+    ///   - bundle: the bundle where the file is located
+    /// - Returns: an optional serialized JSONObject
+    /// - Throws: throws an error in case of failure or invalid JSON data
+    class func jsonObject(from jsonFilename: String, bundle: Bundle = .main) throws -> JSONObject? {
+        guard let filePath = bundle.path(forResource: jsonFilename, ofType: "json") else {
+            return nil
+        }
+        
+        let url = URL(fileURLWithPath: filePath)
+        
+        return try jsonObject(from: Data(contentsOf: url, options: .uncached))
+    }
+}
diff --git a/Example/MatrioskaExample/MatrioskaCodeViewController.swift b/Example/MatrioskaExample/MatrioskaCodeViewController.swift
new file mode 100644
index 0000000..fb7a35f
--- /dev/null
+++ b/Example/MatrioskaExample/MatrioskaCodeViewController.swift
@@ -0,0 +1,57 @@
+//
+//  MatrioskaCodeViewController.swift
+//  MatrioskaExample
+//
+//  Created by Mathias Aichinger on 19/01/2017.
+//  Copyright © 2017 runtastic. All rights reserved.
+//
+
+import UIKit
+import Matrioska
+import SnapKit
+
+class MatrioskaCodeViewController: UIViewController {
+
+    let rootComponent = ClusterLayout.stack(
+        children: [
+            tileComponent(meta: TileConfig(text: "One", color: .red)),
+            tileComponent(meta: TileConfig(text: "Two", color: .green)),
+            ClusterLayout.stack(
+                children: [
+                    tileComponent(meta: TileConfig(text: "A", color: .red)),
+                    tileComponent(meta: TileConfig(text: "B", color: .green)),
+                    tileComponent(meta: TileConfig(text: "C", color: .orange)),
+                    tileComponent(meta: TileConfig(text: "D", color: .yellow))
+                    ],
+                meta: ClusterLayout.StackConfig(axis: .horizontal)
+            ),
+            tileComponent(meta: TileConfig(text: "Three", color: .orange)),
+            tileComponent(meta: TileConfig(text: "Four", color: .yellow))
+            ],
+        meta: ClusterLayout.StackConfig(title: "Test",
+                                        spacing: CGFloat(10.0),
+                                        axis: .vertical,
+                                        preserveParentWidth: true,
+                                        backgroundColor: .blue)
+    )
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        view.backgroundColor = .red
+        
+        guard let rootViewController = rootComponent.viewController(), let rootView = rootViewController.view else {
+            return
+        }
+        
+        addChildViewController(rootViewController)
+        view.addSubview(rootView)
+        rootViewController.didMove(toParentViewController: self)
+        rootView.snp.makeConstraints { (make) in
+            make.edges.equalTo(self.view).inset(0)
+        }
+    }
+}
+
+private func tileComponent(meta: TileConfig) -> Component {
+    return Component.single(viewBuilder: TileViewController.init(meta:), meta: meta)
+}
diff --git a/Example/MatrioskaExample/TileViewController.swift b/Example/MatrioskaExample/TileViewController.swift
index 25a23cb..2e2c222 100644
--- a/Example/MatrioskaExample/TileViewController.swift
+++ b/Example/MatrioskaExample/TileViewController.swift
@@ -15,7 +15,10 @@ struct TileConfig: ExpressibleByComponentMeta {
     
     init?(meta: ComponentMeta) {
         text = meta["text"] as? String
-        color = meta["color"] as? UIColor
+        
+        let hexColor = meta["color"] as? String
+        let color = UIColor(hexString: hexColor ?? "")
+        self.color = color
     }
     
     init(text: String?, color: UIColor) {
diff --git a/Example/MatrioskaExample/app_structure.json b/Example/MatrioskaExample/app_structure.json
new file mode 100644
index 0000000..b655342
--- /dev/null
+++ b/Example/MatrioskaExample/app_structure.json
@@ -0,0 +1,70 @@
+{
+    "structure": {
+        "type": "tabbar",
+        "meta": {
+            "default_tab_id": "main_tab"
+        },
+        "children": [
+                     {
+                     "type": "navigation",
+                     "meta": {
+                     "title": "history_title",
+                     "icon_name": "home"
+                     },
+                     "children": [
+                                  {
+                                  "type": "stack",
+                                  "meta": {
+                                  "background_color": "1111AB"
+                                  },
+                                  "children": [
+                                               {
+                                               "type": "tile",
+                                               "meta": {
+                                               "text": "test",
+                                               "color": "FF6532"
+                                               }
+                                               },
+                                               {
+                                               "type": "stack",
+                                               "meta": {
+                                               "axis": 0
+                                               },
+                                               "children": [
+                                                            {
+                                                            "type": "tile",
+                                                            "meta": {
+                                                            "text": "test",
+                                                            "color": "FF6532"
+                                                            }
+                                                            },
+                                                            {
+                                                            "type": "tile",
+                                                            "meta": {
+                                                            "text": "test",
+                                                            "color": "F8B53D"
+                                                            }
+                                                            },
+                                                            {
+                                                            "type": "tile",
+                                                            "meta": {
+                                                            "text": "test",
+                                                            "color": "FF6532"
+                                                            }
+                                                            }
+                                                            ]
+                                               }
+                                               ]
+                                  }
+                                  ]
+                     },
+                     {
+                     "type": "matrioska",
+                     "meta": {
+                     "title": "main_tab_title",
+                     "icon_name": "list"
+                     }
+                     }
+                     ]
+    }
+}