You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2022/03/27 01:06:37 UTC

[camel-karavan] branch main updated: Karavan view in VSCode (#234)

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new 5356ca4  Karavan view in VSCode (#234)
5356ca4 is described below

commit 5356ca48975220eb6c4eb5115d96a9e870562714
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Sat Mar 26 21:06:33 2022 -0400

    Karavan view in VSCode (#234)
    
    * Redesign vscode extension
    
    * Show integrations
    
    * Kamelets list
    
    * Component list
    
    * Dsl list
    
    * Filter non Integration yamls
    
    * Icons
    
    * Open integration
    
    * Remove target folder from scan
---
 karavan-core/src/core/api/CamelDefinitionYaml.ts   |  27 ++-
 karavan-core/test/beans.spec.ts                    |   2 +-
 karavan-core/test/beans2.yaml                      |   2 +-
 karavan-core/test/restDsl.spec.ts                  |   2 +-
 karavan-core/test/restDsl.yaml                     |   2 +-
 .../{docker-compose.yml => docker-compose.yaml}    |   0
 karavan-demo/postman/postman.yaml                  |   2 +-
 karavan-designer/src/designer/KaravanDesigner.tsx  |   2 +-
 karavan-vscode/icons/dark/crd.svg                  |  46 +++++
 karavan-vscode/icons/dark/karavan.svg              | 160 +++++++++++++++
 karavan-vscode/icons/dark/refresh.svg              |   1 +
 karavan-vscode/icons/karavan-mono-24x24.svg        | 160 +++++++++++++++
 karavan-vscode/icons/letter-k.svg                  |  64 ++++++
 karavan-vscode/icons/light/crd.svg                 |  46 +++++
 karavan-vscode/icons/light/karavan.svg             | 160 +++++++++++++++
 karavan-vscode/icons/light/refresh.svg             |   1 +
 karavan-vscode/icons/plain.svg                     |  67 ++++++
 karavan-vscode/package.json                        |  90 +++++++-
 karavan-vscode/src/componentView.ts                |  70 +++++++
 karavan-vscode/src/designerView.ts                 | 150 ++++++++++++++
 karavan-vscode/src/dslView.ts                      |  70 +++++++
 karavan-vscode/src/extension.ts                    | 227 +++------------------
 karavan-vscode/src/integrationView.ts              |  75 +++++++
 karavan-vscode/src/kameletView.ts                  |  69 +++++++
 karavan-vscode/src/utils.ts                        | 115 +++++++++++
 25 files changed, 1393 insertions(+), 217 deletions(-)

diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts b/karavan-core/src/core/api/CamelDefinitionYaml.ts
index d48dd28..d2024a9 100644
--- a/karavan-core/src/core/api/CamelDefinitionYaml.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts
@@ -181,22 +181,35 @@ export class CamelDefinitionYaml {
         const integration: Integration = Integration.createNew(filename);
         const fromYaml: any = yaml.load(text);
         const camelized: any = CamelUtil.camelizeObject(fromYaml);
-        if (Array.isArray(camelized)) {
-            integration.crd = false;
-            const flows: any[] = camelized;
-            integration.spec.flows?.push(...this.flowsToCamelElements(flows));
-            integration.spec.dependencies = this.modelineToDependency(text);
-            // integration.spec.traits = this.traitsToCamelElements(flows); // TODO: Plain yaml Trait ???
-        } else {
+        if (camelized?.apiVersion && camelized.apiVersion.startsWith('camel.apache.org') && camelized.kind && camelized.kind === 'Integration') {
             integration.crd = true;
+            if (camelized?.metadata?.name) integration.metadata.name = camelized?.metadata?.name;
             const int: Integration = new Integration({...camelized});
             integration.spec.flows?.push(...this.flowsToCamelElements(int.spec.flows || []));
             integration.spec.dependencies = this.dependenciesToDependency(int.spec.dependencies);
             if (int.spec.traits) integration.spec.traits = TraitApi.traitsFromYaml(int.spec.traits);
+        } else if (Array.isArray(camelized)) {
+            integration.crd = false;
+            const flows: any[] = camelized;
+            integration.spec.flows?.push(...this.flowsToCamelElements(flows));
+            integration.spec.dependencies = this.modelineToDependency(text);
+            // integration.spec.traits = this.traitsToCamelElements(flows); // TODO: Plain yaml Trait ???
         }
         return integration;
     }
 
+    static yamlIsIntegration = (text: string): boolean => {
+        const fromYaml: any = yaml.load(text);
+        const camelized: any = CamelUtil.camelizeObject(fromYaml);
+        if (camelized?.apiVersion && camelized.apiVersion.startsWith('camel.apache.org') && camelized.kind && camelized.kind === 'Integration') {
+            return true;
+        } else if (Array.isArray(camelized)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     static dependenciesToDependency = (deps?: any[]): Dependency[] => {
         const result: Dependency[] = [];
         deps?.forEach((d: any) => result.push(Dependency.createNew(d.toString())));
diff --git a/karavan-core/test/beans.spec.ts b/karavan-core/test/beans.spec.ts
index b2e57a1..6e7c7e3 100644
--- a/karavan-core/test/beans.spec.ts
+++ b/karavan-core/test/beans.spec.ts
@@ -39,7 +39,7 @@ describe('bean configuration', () => {
     it('Read beans from Integration', () => {
         const yaml = fs.readFileSync('test/beans2.yaml',{encoding:'utf8', flag:'r'});
         const i = CamelDefinitionYaml.yamlToIntegration("beans.yaml", yaml);
-        expect(i.metadata.name).to.equal('beans.yaml');
+        expect(i.metadata.name).to.equal('Beans');
         expect(i.kind).to.equal('Integration');
         expect(i.spec.flows?.length).to.equal(3);
         expect(i.crd).to.equal(true);
diff --git a/karavan-core/test/beans2.yaml b/karavan-core/test/beans2.yaml
index 4bf83d1..2b3260e 100644
--- a/karavan-core/test/beans2.yaml
+++ b/karavan-core/test/beans2.yaml
@@ -1,7 +1,7 @@
 apiVersion: camel.apache.org/v1
 kind: Integration
 metadata:
-  name: test1.yaml
+  name: Beans
 spec:
   flows:
   - beans:
diff --git a/karavan-core/test/restDsl.spec.ts b/karavan-core/test/restDsl.spec.ts
index a3b9f32..200e763 100644
--- a/karavan-core/test/restDsl.spec.ts
+++ b/karavan-core/test/restDsl.spec.ts
@@ -29,7 +29,7 @@ describe('REST DSL', () => {
     it('YAML <-> Object 1', () => {
         const yaml = fs.readFileSync('test/restDsl.yaml', {encoding: 'utf8', flag: 'r'});
         const i = CamelDefinitionYaml.yamlToIntegration("test1.yaml", yaml);
-        expect(i.metadata.name).to.equal('test1.yaml');
+        expect(i.metadata.name).to.equal('RestDsl');
         expect(i.kind).to.equal('Integration');
         expect(i.spec.flows?.length).to.equal(3);
         expect(i.crd).to.equal(true);
diff --git a/karavan-core/test/restDsl.yaml b/karavan-core/test/restDsl.yaml
index 0f73c59..e1be0d2 100644
--- a/karavan-core/test/restDsl.yaml
+++ b/karavan-core/test/restDsl.yaml
@@ -1,7 +1,7 @@
 apiVersion: camel.apache.org/v1
 kind: Integration
 metadata:
-  name: rest-dsl-example.yaml
+  name: RestDsl
 spec:
   flows:
     - rest-configuration:
diff --git a/karavan-demo/postman/docker-compose.yml b/karavan-demo/postman/docker-compose.yaml
similarity index 100%
rename from karavan-demo/postman/docker-compose.yml
rename to karavan-demo/postman/docker-compose.yaml
diff --git a/karavan-demo/postman/postman.yaml b/karavan-demo/postman/postman.yaml
index 3084a05..a111c3c 100644
--- a/karavan-demo/postman/postman.yaml
+++ b/karavan-demo/postman/postman.yaml
@@ -1,7 +1,7 @@
 apiVersion: camel.apache.org/v1
 kind: Integration
 metadata:
-  name: postman.yaml
+  name: Postman Demo
 spec:
   flows:
     - rest:
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx
index 91ee15e..28ee491 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -52,7 +52,7 @@ export class KaravanDesigner extends React.Component<Props, State> {
 
     public state: State = {
         tab: 'routes',
-        integration: this.props.yaml
+        integration: this.props.yaml && CamelDefinitionYaml.yamlIsIntegration(this.props.yaml)
             ? CamelDefinitionYaml.yamlToIntegration(this.props.filename, this.props.yaml)
             : Integration.createNew(this.props.filename),
         key: "",
diff --git a/karavan-vscode/icons/dark/crd.svg b/karavan-vscode/icons/dark/crd.svg
new file mode 100644
index 0000000..5e629f4
--- /dev/null
+++ b/karavan-vscode/icons/dark/crd.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="16px"
+   height="16px"
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg828"
+   sodipodi:docname="crd.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs832" />
+  <sodipodi:namedview
+     id="namedview830"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="44.9375"
+     inkscape:cx="1.9582754"
+     inkscape:cy="8.2670376"
+     inkscape:window-width="1312"
+     inkscape:window-height="969"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg828" />
+  <path
+     d="M9.449 9.15a.283.283 0 01.067.006l.003-.004 1.734.293a3.435 3.435 0 01-1.388 1.744l-.673-1.626.002-.002a.294.294 0 01.255-.41zm-2.732.073a.294.294 0 01.085.344l.005.006-.666 1.61A3.448 3.448 0 014.757 9.45l1.72-.292.002.004a.288.288 0 01.238.06zm1.433.681a.293.293 0 01.108.113h.006l.848 1.532a3.443 3.443 0 01-2.218-.002l.845-1.529h.002a.293.293 0 01.409-.114zM9.633 7.63l1.3-1.163c.4.647.575 1.408.502 2.164l-1.684-.485-.002-.007a.294.294 0 01-.115-.504V7.63zm-1.067-.884a.294.294 0 [...]
+     fill="#000"
+     id="path824"
+     style="fill:#c5c5c5;fill-opacity:1" />
+  <path
+     fill-rule="evenodd"
+     clip-rule="evenodd"
+     d="M14.6 3.714l1.375 5.97a1.049 1.049 0 01-.04.595 1.041 1.041 0 01-.166.298l-3.85 4.789a1.05 1.05 0 01-.372.29c-.026.013-.054.024-.082.035a1.086 1.086 0 01-.377.071l-6.175.002a1.096 1.096 0 01-.778-.338l-.007-.007c-.016-.017-.032-.034-.047-.053L.231 10.58a1.101 1.101 0 01-.167-.3 1.067 1.067 0 01-.039-.593l1.373-5.971A1.073 1.073 0 011.973 3L7.537.341a1.072 1.072 0 01.923 0l5.564 2.657a1.074 1.074 0 01.576.716zm-4.341 8.427a1.123 1.123 0 01-.056-.134 4.334 4.334 0 001.92-2.415l.142 [...]
+     fill="#000"
+     id="path826"
+     style="fill:#c5c5c5;fill-opacity:1" />
+</svg>
diff --git a/karavan-vscode/icons/dark/karavan.svg b/karavan-vscode/icons/dark/karavan.svg
new file mode 100644
index 0000000..932d351
--- /dev/null
+++ b/karavan-vscode/icons/dark/karavan.svg
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   version="1.1"
+   preserveAspectRatio="xMidYMid"
+   id="svg50"
+   sodipodi:docname="karavan.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   inkscape:export-filename="/Users/mgubaidu/projects/oss/camel-karavan/karavan-vscode/icons/karavan-mono-24x24.png"
+   inkscape:export-xdpi="95.999992"
+   inkscape:export-ydpi="95.999992"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview52"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="6"
+     inkscape:cx="136.33333"
+     inkscape:cy="80.75"
+     inkscape:window-width="2560"
+     inkscape:window-height="1387"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg50"
+     width="24px" />
+  <defs
+     id="defs31">
+    <circle
+       id="path-1"
+       cx="128"
+       cy="128.00015"
+       r="128" />
+    <linearGradient
+       x1="-26.051073"
+       y1="271.33054"
+       x2="254.31573"
+       y2="0.047514945"
+       id="linearGradient-3"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop10"
+         style="stop-color:#4790bb;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="10.996%"
+         id="stop12"
+         style="stop-color:#64b7db;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="94.502%"
+         id="stop14"
+         style="stop-color:#326ea0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       x1="-32.163429"
+       y1="277.02905"
+       x2="259.33835"
+       y2="-5.0281582"
+       id="linearGradient-4"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop17" />
+      <stop
+         stop-color="#F79A23"
+         offset="8.0478%"
+         id="stop19" />
+      <stop
+         stop-color="#E97826"
+         offset="41.874%"
+         id="stop21" />
+    </linearGradient>
+    <linearGradient
+       x1="217.94496"
+       y1="67.504837"
+       x2="99.458817"
+       y2="247.00549"
+       id="linearGradient-5"
+       gradientTransform="scale(0.96441978,1.0368929)"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient-4">
+      <stop
+         stop-color="#F6E423"
+         offset="0%"
+         id="stop24"
+         style="stop-color:#92d6d5;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="41.191%"
+         id="stop26"
+         style="stop-color:#79b7cc;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="73.271%"
+         id="stop28"
+         style="stop-color:#5891c5;stop-opacity:1" />
+    </linearGradient>
+    <mask
+       id="mask-2"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use33"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+    <mask
+       id="mask-2-7"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use137"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+  </defs>
+  <g
+     id="g36"
+     style="fill:#c5c5c5;fill-opacity:1"
+     transform="matrix(0.09346922,0,0,0.09375006,-116.42812,-114.50002)" />
+  <g
+     id="g1275"
+     style="fill:#c5c5c5;fill-opacity:1"
+     transform="matrix(0.09346922,0,0,0.09375006,0.0718809,-1.4305124e-5)">
+    <path
+       d="m 128.74719,54.004528 c -10.98485,5.495372 0,27.466068 0,27.466068 -32.973011,27.483724 -25.9672,74.429124 -64.435392,74.429124 -20.970343,0 -42.242226,-24.0768 -64.23273709,-38.82804 -0.28309669,3.47897 -0.78535974,6.97247 -0.78535974,10.52442 0,48.09504 26.26287383,89.92436 65.41967783,111.89721 10.952683,-1.3796 22.838636,-4.11444 31.050991,-9.59255 43.14527,-28.76482 53.85703,-83.49096 71.48633,-109.92509 10.97897,-16.492 62.43429,-15.06102 65.90679,-22.01013 5.50126,-10.99 [...]
+       fill="#ffffff"
+       fill-rule="nonzero"
+       mask="url(#mask-2-7)"
+       id="path150"
+       transform="translate(-0.76903282,-0.13309639)"
+       style="fill:#c5c5c5;fill-opacity:1" />
+    <path
+       d="M 128,256 C 57.307552,256 0,198.69245 0,128 0,57.307552 57.307552,0 128,0 c 70.69245,0 128,57.307552 128,128 0,70.69245 -57.30755,128 -128,128 z m 0,-9.76795 C 193.29776,246.23205 246.23205,193.29776 246.23205,128 246.23205,62.702243 193.29776,9.7679529 128,9.7679529 62.702243,9.7679529 9.7679529,62.702243 9.7679529,128 9.7679529,193.29776 62.702243,246.23205 128,246.23205 Z"
+       fill="url(#linearGradient-4)"
+       fill-rule="nonzero"
+       mask="url(#mask-2)"
+       id="path40"
+       style="fill:#c5c5c5;fill-opacity:1" />
+  </g>
+</svg>
diff --git a/karavan-vscode/icons/dark/refresh.svg b/karavan-vscode/icons/dark/refresh.svg
new file mode 100644
index 0000000..d79fdaa
--- /dev/null
+++ b/karavan-vscode/icons/dark/refresh.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1. [...]
\ No newline at end of file
diff --git a/karavan-vscode/icons/karavan-mono-24x24.svg b/karavan-vscode/icons/karavan-mono-24x24.svg
new file mode 100644
index 0000000..92ffc08
--- /dev/null
+++ b/karavan-vscode/icons/karavan-mono-24x24.svg
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   version="1.1"
+   preserveAspectRatio="xMidYMid"
+   id="svg50"
+   sodipodi:docname="karavan-mono-24x24.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   inkscape:export-filename="/Users/mgubaidu/projects/oss/camel-karavan/karavan-vscode/icons/karavan-mono-24x24.png"
+   inkscape:export-xdpi="95.999992"
+   inkscape:export-ydpi="95.999992"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview52"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="2"
+     inkscape:cx="138.5"
+     inkscape:cy="160.75"
+     inkscape:window-width="2560"
+     inkscape:window-height="1387"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg50"
+     width="24px" />
+  <defs
+     id="defs31">
+    <circle
+       id="path-1"
+       cx="128"
+       cy="128.00015"
+       r="128" />
+    <linearGradient
+       x1="-26.051073"
+       y1="271.33054"
+       x2="254.31573"
+       y2="0.047514945"
+       id="linearGradient-3"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop10"
+         style="stop-color:#4790bb;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="10.996%"
+         id="stop12"
+         style="stop-color:#64b7db;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="94.502%"
+         id="stop14"
+         style="stop-color:#326ea0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       x1="-32.163429"
+       y1="277.02905"
+       x2="259.33835"
+       y2="-5.0281582"
+       id="linearGradient-4"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop17" />
+      <stop
+         stop-color="#F79A23"
+         offset="8.0478%"
+         id="stop19" />
+      <stop
+         stop-color="#E97826"
+         offset="41.874%"
+         id="stop21" />
+    </linearGradient>
+    <linearGradient
+       x1="217.94496"
+       y1="67.504837"
+       x2="99.458817"
+       y2="247.00549"
+       id="linearGradient-5"
+       gradientTransform="scale(0.96441978,1.0368929)"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient-4">
+      <stop
+         stop-color="#F6E423"
+         offset="0%"
+         id="stop24"
+         style="stop-color:#92d6d5;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="41.191%"
+         id="stop26"
+         style="stop-color:#79b7cc;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="73.271%"
+         id="stop28"
+         style="stop-color:#5891c5;stop-opacity:1" />
+    </linearGradient>
+    <mask
+       id="mask-2"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use33"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+    <mask
+       id="mask-2-7"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use137"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+  </defs>
+  <g
+     id="g36"
+     style="fill:#000000"
+     transform="matrix(0.09346922,0,0,0.09375006,-116.42812,-114.50002)" />
+  <g
+     id="g1275"
+     style="fill:#000000"
+     transform="matrix(0.09346922,0,0,0.09375006,0.0718809,-1.4305124e-5)">
+    <path
+       d="m 128.74719,54.004528 c -10.98485,5.495372 0,27.466068 0,27.466068 -32.973011,27.483724 -25.9672,74.429124 -64.435392,74.429124 -20.970343,0 -42.242226,-24.0768 -64.23273709,-38.82804 -0.28309669,3.47897 -0.78535974,6.97247 -0.78535974,10.52442 0,48.09504 26.26287383,89.92436 65.41967783,111.89721 10.952683,-1.3796 22.838636,-4.11444 31.050991,-9.59255 43.14527,-28.76482 53.85703,-83.49096 71.48633,-109.92509 10.97897,-16.492 62.43429,-15.06102 65.90679,-22.01013 5.50126,-10.99 [...]
+       fill="#ffffff"
+       fill-rule="nonzero"
+       mask="url(#mask-2-7)"
+       id="path150"
+       transform="translate(-0.76903282,-0.13309639)"
+       style="fill:#000000;fill-opacity:1" />
+    <path
+       d="M 128,256 C 57.307552,256 0,198.69245 0,128 0,57.307552 57.307552,0 128,0 c 70.69245,0 128,57.307552 128,128 0,70.69245 -57.30755,128 -128,128 z m 0,-9.76795 C 193.29776,246.23205 246.23205,193.29776 246.23205,128 246.23205,62.702243 193.29776,9.7679529 128,9.7679529 62.702243,9.7679529 9.7679529,62.702243 9.7679529,128 9.7679529,193.29776 62.702243,246.23205 128,246.23205 Z"
+       fill="url(#linearGradient-4)"
+       fill-rule="nonzero"
+       mask="url(#mask-2)"
+       id="path40"
+       style="fill:#000000;fill-opacity:1" />
+  </g>
+</svg>
diff --git a/karavan-vscode/icons/letter-k.svg b/karavan-vscode/icons/letter-k.svg
new file mode 100644
index 0000000..a195bbb
--- /dev/null
+++ b/karavan-vscode/icons/letter-k.svg
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="14"
+   height="20"
+   viewBox="0 0 14 20"
+   id="icon"
+   version="1.1"
+   sodipodi:docname="letter-k.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <sodipodi:namedview
+     id="namedview836"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="22.46875"
+     inkscape:cx="10.926287"
+     inkscape:cy="16.511822"
+     inkscape:window-width="1914"
+     inkscape:window-height="1170"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="icon" />
+  <defs
+     id="defs826">
+    <style
+       id="style824">.cls-1{fill:none;}</style>
+  </defs>
+  <title
+     id="title828">letter--Kk</title>
+  <polygon
+     points="9.93,17.22 12.89,23 15,23 11.11,15.43 15,9 12.89,9 9,15.55 9,9 7,9 7,23 9,23 9,18.71 "
+     id="polygon830"
+     transform="matrix(1,0,0,0.80607987,-4.062587,-2.9821181)"
+     style="fill:#326ce5;fill-opacity:1" />
+  <rect
+     id="_Transparent_Rectangle_"
+     data-name="&lt;Transparent Rectangle&gt;"
+     class="cls-1"
+     width="32"
+     height="32"
+     x="0"
+     y="0" />
+  <metadata
+     id="metadata998">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:title>letter--Kk</dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/karavan-vscode/icons/light/crd.svg b/karavan-vscode/icons/light/crd.svg
new file mode 100644
index 0000000..22b0740
--- /dev/null
+++ b/karavan-vscode/icons/light/crd.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="16px"
+   height="16px"
+   viewBox="0 0 16 16"
+   version="1.1"
+   id="svg932"
+   sodipodi:docname="crd.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs936" />
+  <sodipodi:namedview
+     id="namedview934"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="44.9375"
+     inkscape:cx="1.9582754"
+     inkscape:cy="8.2670376"
+     inkscape:window-width="1296"
+     inkscape:window-height="969"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg932" />
+  <path
+     d="M9.449 9.15a.283.283 0 01.067.006l.003-.004 1.734.293a3.435 3.435 0 01-1.388 1.744l-.673-1.626.002-.002a.294.294 0 01.255-.41zm-2.732.073a.294.294 0 01.085.344l.005.006-.666 1.61A3.448 3.448 0 014.757 9.45l1.72-.292.002.004a.288.288 0 01.238.06zm1.433.681a.293.293 0 01.108.113h.006l.848 1.532a3.443 3.443 0 01-2.218-.002l.845-1.529h.002a.293.293 0 01.409-.114zM9.633 7.63l1.3-1.163c.4.647.575 1.408.502 2.164l-1.684-.485-.002-.007a.294.294 0 01-.115-.504V7.63zm-1.067-.884a.294.294 0 [...]
+     fill="#000"
+     id="path928"
+     style="fill:#424242;fill-opacity:1" />
+  <path
+     fill-rule="evenodd"
+     clip-rule="evenodd"
+     d="M14.6 3.714l1.375 5.97a1.049 1.049 0 01-.04.595 1.041 1.041 0 01-.166.298l-3.85 4.789a1.05 1.05 0 01-.372.29c-.026.013-.054.024-.082.035a1.086 1.086 0 01-.377.071l-6.175.002a1.096 1.096 0 01-.778-.338l-.007-.007c-.016-.017-.032-.034-.047-.053L.231 10.58a1.101 1.101 0 01-.167-.3 1.067 1.067 0 01-.039-.593l1.373-5.971A1.073 1.073 0 011.973 3L7.537.341a1.072 1.072 0 01.923 0l5.564 2.657a1.074 1.074 0 01.576.716zm-4.341 8.427a1.123 1.123 0 01-.056-.134 4.334 4.334 0 001.92-2.415l.142 [...]
+     fill="#000"
+     id="path930"
+     style="fill:#424242;fill-opacity:1" />
+</svg>
diff --git a/karavan-vscode/icons/light/karavan.svg b/karavan-vscode/icons/light/karavan.svg
new file mode 100644
index 0000000..295f8eb
--- /dev/null
+++ b/karavan-vscode/icons/light/karavan.svg
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   version="1.1"
+   preserveAspectRatio="xMidYMid"
+   id="svg50"
+   sodipodi:docname="karavan.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   inkscape:export-filename="/Users/mgubaidu/projects/oss/camel-karavan/karavan-vscode/icons/karavan-mono-24x24.png"
+   inkscape:export-xdpi="95.999992"
+   inkscape:export-ydpi="95.999992"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview52"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="2"
+     inkscape:cx="132"
+     inkscape:cy="160.75"
+     inkscape:window-width="2560"
+     inkscape:window-height="1387"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg50"
+     width="24px" />
+  <defs
+     id="defs31">
+    <circle
+       id="path-1"
+       cx="128"
+       cy="128.00015"
+       r="128" />
+    <linearGradient
+       x1="-26.051073"
+       y1="271.33054"
+       x2="254.31573"
+       y2="0.047514945"
+       id="linearGradient-3"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop10"
+         style="stop-color:#4790bb;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="10.996%"
+         id="stop12"
+         style="stop-color:#64b7db;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="94.502%"
+         id="stop14"
+         style="stop-color:#326ea0;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       x1="-32.163429"
+       y1="277.02905"
+       x2="259.33835"
+       y2="-5.0281582"
+       id="linearGradient-4"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#F69923"
+         offset="0%"
+         id="stop17" />
+      <stop
+         stop-color="#F79A23"
+         offset="8.0478%"
+         id="stop19" />
+      <stop
+         stop-color="#E97826"
+         offset="41.874%"
+         id="stop21" />
+    </linearGradient>
+    <linearGradient
+       x1="217.94496"
+       y1="67.504837"
+       x2="99.458817"
+       y2="247.00549"
+       id="linearGradient-5"
+       gradientTransform="scale(0.96441978,1.0368929)"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient-4">
+      <stop
+         stop-color="#F6E423"
+         offset="0%"
+         id="stop24"
+         style="stop-color:#92d6d5;stop-opacity:1" />
+      <stop
+         stop-color="#F79A23"
+         offset="41.191%"
+         id="stop26"
+         style="stop-color:#79b7cc;stop-opacity:1" />
+      <stop
+         stop-color="#E97826"
+         offset="73.271%"
+         id="stop28"
+         style="stop-color:#5891c5;stop-opacity:1" />
+    </linearGradient>
+    <mask
+       id="mask-2"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use33"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+    <mask
+       id="mask-2-7"
+       fill="#ffffff">
+      <use
+         xlink:href="#path-1"
+         id="use137"
+         x="0"
+         y="0"
+         width="100%"
+         height="100%" />
+    </mask>
+  </defs>
+  <g
+     id="g36"
+     style="fill:#424242;fill-opacity:1"
+     transform="matrix(0.09346922,0,0,0.09375006,-116.42812,-114.50002)" />
+  <g
+     id="g1275"
+     style="fill:#424242;fill-opacity:1"
+     transform="matrix(0.09346922,0,0,0.09375006,0.0718809,-1.4305124e-5)">
+    <path
+       d="m 128.74719,54.004528 c -10.98485,5.495372 0,27.466068 0,27.466068 -32.973011,27.483724 -25.9672,74.429124 -64.435392,74.429124 -20.970343,0 -42.242226,-24.0768 -64.23273709,-38.82804 -0.28309669,3.47897 -0.78535974,6.97247 -0.78535974,10.52442 0,48.09504 26.26287383,89.92436 65.41967783,111.89721 10.952683,-1.3796 22.838636,-4.11444 31.050991,-9.59255 43.14527,-28.76482 53.85703,-83.49096 71.48633,-109.92509 10.97897,-16.492 62.43429,-15.06102 65.90679,-22.01013 5.50126,-10.99 [...]
+       fill="#ffffff"
+       fill-rule="nonzero"
+       mask="url(#mask-2-7)"
+       id="path150"
+       transform="translate(-0.76903282,-0.13309639)"
+       style="fill:#424242;fill-opacity:1" />
+    <path
+       d="M 128,256 C 57.307552,256 0,198.69245 0,128 0,57.307552 57.307552,0 128,0 c 70.69245,0 128,57.307552 128,128 0,70.69245 -57.30755,128 -128,128 z m 0,-9.76795 C 193.29776,246.23205 246.23205,193.29776 246.23205,128 246.23205,62.702243 193.29776,9.7679529 128,9.7679529 62.702243,9.7679529 9.7679529,62.702243 9.7679529,128 9.7679529,193.29776 62.702243,246.23205 128,246.23205 Z"
+       fill="url(#linearGradient-4)"
+       fill-rule="nonzero"
+       mask="url(#mask-2)"
+       id="path40"
+       style="fill:#424242;fill-opacity:1" />
+  </g>
+</svg>
diff --git a/karavan-vscode/icons/light/refresh.svg b/karavan-vscode/icons/light/refresh.svg
new file mode 100644
index 0000000..e034574
--- /dev/null
+++ b/karavan-vscode/icons/light/refresh.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1. [...]
\ No newline at end of file
diff --git a/karavan-vscode/icons/plain.svg b/karavan-vscode/icons/plain.svg
new file mode 100644
index 0000000..453ffac
--- /dev/null
+++ b/karavan-vscode/icons/plain.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="32px"
+   height="32px"
+   viewBox="0 0 32 32"
+   id="icon"
+   version="1.1"
+   sodipodi:docname="plain.svg"
+   inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview1002"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     showgrid="false"
+     inkscape:zoom="9.7781858"
+     inkscape:cx="25.004639"
+     inkscape:cy="23.675149"
+     inkscape:window-width="1296"
+     inkscape:window-height="969"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="icon" />
+  <defs
+     id="defs988">
+    <style
+       id="style986">
+      .cls-1 {
+        fill: none;
+      }
+    </style>
+  </defs>
+  <path
+     d="M10,10H2V2h8ZM4,8H8V4H4Z"
+     id="path990"
+     style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+  <path
+     d="M30,30H22V22h8Zm-6-2h4V24H24Z"
+     id="path992"
+     style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+  <path
+     d="M20,27H8A6,6,0,0,1,8,15v2a4,4,0,0,0,0,8H20Z"
+     id="path994"
+     style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+  <path
+     d="M24,17V15a4,4,0,0,0,0-8H12V5H24a6,6,0,0,1,0,12Z"
+     id="path996"
+     style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+  <path
+     d="M19,11H13l-3,4,6,6,6-6Z"
+     id="path998"
+     style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+  <rect
+     id="_Transparent_Rectangle_"
+     data-name="&lt;Transparent Rectangle&gt;"
+     class="cls-1"
+     width="32"
+     height="32" />
+</svg>
diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json
index 647274d..a1de72c 100644
--- a/karavan-vscode/package.json
+++ b/karavan-vscode/package.json
@@ -45,7 +45,8 @@
     "onCommand:karavan.create-crd",
     "onCommand:karavan.create-yaml",
     "onCommand:karavan.jbang-run",
-    "onCommand:karavan.open"
+    "onCommand:karavan.open",
+    "onView:integrations"
   ],
   "main": "./dist/extension.js",
   "contributes": {
@@ -116,7 +117,39 @@
         "command": "karavan.jbang-run",
         "title": "Karavan: JBang Run",
         "icon": "./icons/run.png"
-      }
+      },
+      {
+				"command": "integrations.refresh",
+				"title": "Refresh",
+				"icon": {
+					"light": "icons/light/refresh.svg",
+					"dark": "icons/dark/refresh.svg"
+				}
+			},
+      {
+				"command": "kamelets.refresh",
+				"title": "Refresh",
+				"icon": {
+					"light": "icons/light/refresh.svg",
+					"dark": "icons/dark/refresh.svg"
+				}
+			},
+      {
+				"command": "components.refresh",
+				"title": "Refresh",
+				"icon": {
+					"light": "icons/light/refresh.svg",
+					"dark": "icons/dark/refresh.svg"
+				}
+			},
+      {
+				"command": "dsl.refresh",
+				"title": "Refresh",
+				"icon": {
+					"light": "icons/light/refresh.svg",
+					"dark": "icons/dark/refresh.svg"
+				}
+			}
     ],
     "menus": {
       "explorer/context": [
@@ -148,14 +181,59 @@
           "when": "resourceExtname == .yaml || karavan:loaded",
           "group": "navigation"
         }
-      ]
+      ],
+      "view/title": [
+				{
+					"command": "integrations.refresh",
+					"when": "view == integrations",
+					"group": "navigation"
+				},
+        {
+					"command": "kamelets.refresh",
+					"when": "view == kamelets",
+					"group": "navigation"
+				},
+        {
+					"command": "components.refresh",
+					"when": "view == components",
+					"group": "navigation"
+				},
+        {
+					"command": "dsl.refresh",
+					"when": "view == dsl",
+					"group": "navigation"
+				}
+			]
     },
     "viewsContainers": {
       "activitybar": [
         {
-          "id": "karavan",
+          "id": "karavanView",
           "title": "Karavan",
-          "icon": "webview/icons/camel.svg"
+          "icon": "icons/karavan-mono-24x24.svg"
+        }
+      ]
+    },
+    "views": {
+      "karavanView": [
+        {
+          "id": "integrations",
+          "name": "Integrations"
+        },
+        {
+          "id": "dsl",
+          "name": "Domain Specific Language",
+          "visibility": "collapsed"
+        },
+        {
+          "id": "kamelets",
+          "name": "Kamelets",
+          "visibility": "collapsed"
+        },        
+        {
+          "id": "components",
+          "name": "Components",
+          "visibility": "collapsed"
         }
       ]
     }
@@ -214,4 +292,4 @@
     "rxjs": "7.5.2",
     "uuid": "8.3.2"
   }
-}
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/componentView.ts b/karavan-vscode/src/componentView.ts
new file mode 100644
index 0000000..1d45778
--- /dev/null
+++ b/karavan-vscode/src/componentView.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as path from "path";
+import * as utils from "./utils";
+import * as fs from "fs";
+import { ComponentApi } from "karavan-core/lib/api/ComponentApi";
+import { Component } from "karavan-core/lib/model/ComponentModels";
+import { ThemeIcon } from "vscode";
+
+export class ComponentView implements vscode.TreeDataProvider<ComponentItem> {
+
+    constructor(private context: vscode.ExtensionContext, private rootPath: string | undefined) {
+
+    }
+	private _onDidChangeTreeData: vscode.EventEmitter<ComponentItem | undefined | void> = new vscode.EventEmitter<ComponentItem | undefined | void>();
+	readonly onDidChangeTreeData: vscode.Event<ComponentItem | undefined | void> = this._onDidChangeTreeData.event;
+
+	getTreeItem(element: ComponentItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
+		return element;
+	}
+	getChildren(element?: ComponentItem): vscode.ProviderResult<ComponentItem[]> {
+		const kamelets: ComponentItem[] = [];
+		if (this.rootPath){
+			utils.readComponents(this.context).forEach(s => {
+				const c:Component = ComponentApi.jsonToComponent(s);
+				if (!c.component.deprecated) 
+				kamelets.push(new ComponentItem(c.component.title, c.component.description, c.component.label));
+			})
+		}
+		return Promise.resolve(kamelets);
+	}
+
+	refresh(): void {
+		this._onDidChangeTreeData.fire();
+	}
+}
+
+export class ComponentItem extends vscode.TreeItem {
+
+	constructor(
+		public readonly title: string,
+		public readonly description: string,
+		private readonly type: string,
+		public readonly command?: vscode.Command
+	) {
+		super(title, vscode.TreeItemCollapsibleState.None);
+
+		this.tooltip = this.description;
+		this.description = this.type;
+	}
+
+	iconPath = ThemeIcon.File;
+
+	contextValue = 'component';
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/designerView.ts b/karavan-vscode/src/designerView.ts
new file mode 100644
index 0000000..ae36e8d
--- /dev/null
+++ b/karavan-vscode/src/designerView.ts
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as fs from "fs";
+import * as path from "path";
+import * as utils from "./utils";
+import { CamelDefinitionYaml } from "karavan-core/lib/api/CamelDefinitionYaml";
+import { Integration } from "karavan-core/lib/model/IntegrationDefinition";
+
+const KARAVAN_LOADED = "karavan:loaded";
+const KARAVAN_PANELS: Map<string, vscode.WebviewPanel> = new Map<string, vscode.WebviewPanel>();
+const TERMINALS: Map<string, vscode.Terminal> = new Map<string, vscode.Terminal>();
+
+export class DesignerView {
+
+    constructor(private context: vscode.ExtensionContext, private webviewContent: string) {
+
+    }
+
+    karavanOpen(fullPath: string) {
+        const yaml = fs.readFileSync(path.resolve(fullPath)).toString('utf8');
+        const filename = path.basename(fullPath);
+        const relativePath = utils.getRalativePath(fullPath);
+        const integration = utils.parceYaml(filename, yaml);
+
+        if (integration[0]) {
+            this.openKaravanWebView(filename, relativePath, integration[1]);
+        } else {
+            vscode.window.showErrorMessage("File is not Camel Integration!")
+        }
+    }
+
+    jbangRun(fullPath: string) {
+        if (fullPath.startsWith('webview-panel/webview')) {
+            const filename = Array.from(KARAVAN_PANELS.entries()).filter(({ 1: v }) => v.active).map(([k]) => k)[0];
+            if (filename) {
+                utils.runCamelJbang(filename);
+            }
+        } else {
+            const yaml = fs.readFileSync(path.resolve(fullPath)).toString('utf8');
+            const relativePath = utils.getRalativePath(fullPath);
+            const filename = path.basename(fullPath);
+            const integration = utils.parceYaml(filename, yaml);
+            if (integration[0]) {
+                utils.runCamelJbang(relativePath);
+            } else {
+                vscode.window.showErrorMessage("File is not Camel-K Integration!")
+            }
+        }
+    }
+
+    createIntegration(crd: boolean) {
+        vscode.window
+            .showInputBox({
+                title: crd ? "Create Camel-K Integration CRD" : "Create Camel Integration YAML",
+                ignoreFocusOut: true,
+                prompt: "Integration name",
+                validateInput: (text: string): string | undefined => {
+                    if (!text || text.length === 0) {
+                        return 'Name should not be empty';
+                    } else {
+                        return undefined;
+                    }
+                }
+            }).then(value => {
+                if (value) {
+                    const name = utils.nameFromTitle(value);
+                    const i = Integration.createNew(name);
+                    i.crd = crd;
+                    const yaml = CamelDefinitionYaml.integrationToYaml(i);
+                    const filename = name.toLocaleLowerCase().endsWith('.yaml') ? name : name + '.yaml';
+                    this.openKaravanWebView(filename, filename, yaml);
+                }
+            });
+    }
+
+    openKaravanWebView(filename: string, relativePath: string, yaml?: string) {
+        // Karavan webview
+        const panel = vscode.window.createWebviewPanel(
+            "karavan",
+            filename,
+            vscode.ViewColumn.One,
+            {
+                enableScripts: true,
+                retainContextWhenHidden: true,
+                localResourceRoots: [
+                    vscode.Uri.joinPath(this.context.extensionUri, "dist"),
+                ],
+            }
+        );
+        panel.webview.html = this.webviewContent;
+        panel.iconPath = vscode.Uri.joinPath(
+            this.context.extensionUri,
+            "icons/icon.svg"
+        );
+
+        // Handle messages from the webview
+        panel.webview.onDidReceiveMessage(
+            message => {
+                switch (message.command) {
+                    case 'save':
+                        if (vscode.workspace.workspaceFolders) {
+                            console.log(message);
+                            const uriFolder: vscode.Uri = vscode.workspace.workspaceFolders[0].uri;
+                            const uriFile: vscode.Uri = vscode.Uri.file(path.join(uriFolder.path, message.relativePath));
+                            fs.writeFile(uriFile.fsPath, message.yaml, err => {
+                                if (err) vscode.window.showErrorMessage("Error: " + err?.message);
+                            });
+                        }
+                        break;
+                    case 'getData':
+                        this.sendData(panel, filename, relativePath, yaml);
+                        break;
+                }
+            },
+            undefined,
+            this.context.subscriptions
+        );
+        KARAVAN_PANELS.set(relativePath, panel);
+        vscode.commands.executeCommand("setContext", KARAVAN_LOADED, true);
+    }
+    sendData(panel: vscode.WebviewPanel, filename: string, relativePath: string, yaml?: string) {
+
+        // Read and send Kamelets
+        console.log("Kamelets sent");
+        panel.webview.postMessage({ command: 'kamelets', kamelets: utils.readKamelets(this.context) });
+
+        // Read and send Components
+        console.log("Components sent");
+        panel.webview.postMessage({ command: 'components', components: utils.readComponents(this.context) });
+
+        // Send integration
+        panel.webview.postMessage({ command: 'open', filename: filename, relativePath: relativePath, yaml: yaml });
+    }
+
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/dslView.ts b/karavan-vscode/src/dslView.ts
new file mode 100644
index 0000000..0d8caf4
--- /dev/null
+++ b/karavan-vscode/src/dslView.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as utils from "./utils";
+import { CamelModelMetadata, ElementMeta } from "karavan-core/lib/model/CamelMetadata";
+import { ThemeIcon } from "vscode";
+
+export class DslView implements vscode.TreeDataProvider<DslItem> {
+
+    constructor(private context: vscode.ExtensionContext, private rootPath: string | undefined) {
+
+    }
+	private _onDidChangeTreeData: vscode.EventEmitter<DslItem | undefined | void> = new vscode.EventEmitter<DslItem | undefined | void>();
+	readonly onDidChangeTreeData: vscode.Event<DslItem | undefined | void> = this._onDidChangeTreeData.event;
+
+	getTreeItem(element: DslItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
+		return element;
+	}
+	getChildren(element?: DslItem): vscode.ProviderResult<DslItem[]> {
+		const kamelets: DslItem[] = [];
+		if (this.rootPath){
+			CamelModelMetadata.sort((a, b) => {
+				if (a.title.toLowerCase() < b.title.toLowerCase()) {
+					return -1;
+				}
+				return a.title.toLowerCase() > b.title.toLowerCase() ? 1 : 0;
+			}).forEach((e:ElementMeta) => {
+				kamelets.push(new DslItem(e.title, e.description, e.labels));
+			})
+		}
+		return Promise.resolve(kamelets);
+	}
+
+	refresh(): void {
+		this._onDidChangeTreeData.fire();
+	}
+}
+
+export class DslItem extends vscode.TreeItem {
+
+	constructor(
+		public readonly title: string,
+		public readonly description: string,
+		private readonly type: string,
+		public readonly command?: vscode.Command
+	) {
+		super(title, vscode.TreeItemCollapsibleState.None);
+
+		this.tooltip = this.description;
+		this.description = this.type;
+	}
+
+	iconPath = ThemeIcon.File;
+
+	contextValue = 'component';
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/extension.ts b/karavan-vscode/src/extension.ts
index c980760..d47f3df 100644
--- a/karavan-vscode/src/extension.ts
+++ b/karavan-vscode/src/extension.ts
@@ -16,15 +16,13 @@
  */
 import * as vscode from "vscode";
 import * as fs from "fs";
-import * as path from "path";
-import { CamelDefinitionYaml } from "karavan-core/lib/api/CamelDefinitionYaml";
-import * as jsyaml from 'js-yaml';
-import { Integration } from "karavan-core/lib/model/IntegrationDefinition";
-import { homedir } from "os";
+import { DesignerView } from "./designerView";
+import {IntegrationView} from "./integrationView";
+import { KameletView } from "./kameletView";
+import { ComponentView } from "./componentView";
+import { DslView } from "./dslView";
 
 const KARAVAN_LOADED = "karavan:loaded";
-const KARAVAN_PANELS: Map<string, vscode.WebviewPanel> = new Map<string, vscode.WebviewPanel>();
-const TERMINALS: Map<string, vscode.Terminal> = new Map<string, vscode.Terminal>();
 
 export function activate(context: vscode.ExtensionContext) {
     const webviewContent = fs
@@ -45,210 +43,43 @@ export function activate(context: vscode.ExtensionContext) {
                 .toString()
         );
 
-    // Create new Camel-K Integration CRD command
-    const createCrd = vscode.commands.registerCommand("karavan.create-crd", () => createIntegration(context, webviewContent, true));
+    const designer = new DesignerView(context, webviewContent);
+
+    // Create new Integration CRD command
+    const createCrd = vscode.commands.registerCommand("karavan.create-crd", () => designer.createIntegration(true));
     context.subscriptions.push(createCrd);
 
-    // Create new Camel Integration YAML command
-    const createYaml = vscode.commands.registerCommand("karavan.create-yaml", () => createIntegration(context, webviewContent, false));
+    // Create new Integration YAML command
+    const createYaml = vscode.commands.registerCommand("karavan.create-yaml", () => designer.createIntegration(false));
     context.subscriptions.push(createYaml);
 
     // Open Camel-K integration in designer
-    const open = vscode.commands.registerCommand(
-        "karavan.open",
-        (...args: any[]) => {
-            if (args && args.length > 0) {
-                const yaml = fs.readFileSync(path.resolve(args[0].fsPath)).toString('utf8');
-                const filename = path.basename(args[0].fsPath);
-                const relativePath = getRalativePath(args[0].path);
-                const integration = parceYaml(filename, yaml);
-                if (integration[0]) {
-                    openKaravanWebView(context, webviewContent, filename, relativePath, integration[1]);
-                } else {
-                    vscode.window.showErrorMessage("File is not Camel Integration!")
-                }
-            }
-        }
-    );
+    const open = vscode.commands.registerCommand("karavan.open", (...args: any[]) => designer.karavanOpen(args[0].fsPath));
     context.subscriptions.push(open);
 
-    // Run Camel-K integration in designer
-    const run = vscode.commands.registerCommand(
-        "karavan.jbang-run",
-        (...args: any[]) => {
-            if (args && args.length > 0) {
-                if (args[0].fsPath.startsWith('webview-panel/webview')) {
-                    const filename = Array.from(KARAVAN_PANELS.entries()).filter(({ 1: v }) => v.active).map(([k]) => k)[0];
-                    if (filename) {
-                        runCamelJbang(filename);
-                    }
-                } else {
-                    const yaml = fs.readFileSync(path.resolve(args[0].fsPath)).toString('utf8');
-                    const relativePath = getRalativePath(args[0].fsPath);
-                    const filename = path.basename(args[0].path);
-                    const integration = parceYaml(filename, yaml);
-                    if (integration[0]) {
-                        runCamelJbang(relativePath);
-                    } else {
-                        vscode.window.showErrorMessage("File is not Camel-K Integration!")
-                    }
-                }
-            }
-        }
-    );
+    // Run Integration in designer
+    const run = vscode.commands.registerCommand("karavan.jbang-run", (...args: any[]) => designer.jbangRun(args[0].fsPath));
     context.subscriptions.push(run);
-}
-
-function openKaravanWebView(context: vscode.ExtensionContext, webviewContent: string, filename: string, relativePath: string, yaml?: string) {
-    // Karavan webview
-    const panel = vscode.window.createWebviewPanel(
-        "karavan",
-        filename,
-        vscode.ViewColumn.One,
-        {
-            enableScripts: true,
-            retainContextWhenHidden: true,
-            localResourceRoots: [
-                vscode.Uri.joinPath(context.extensionUri, "dist"),
-            ],
-        }
-    );
-    panel.webview.html = webviewContent;
-    panel.iconPath = vscode.Uri.joinPath(
-        context.extensionUri,
-        "icons/icon.svg"
-    );
-
-    // Handle messages from the webview
-    panel.webview.onDidReceiveMessage(
-        message => {
-            switch (message.command) {
-                case 'save':
-                    if (vscode.workspace.workspaceFolders) {
-                        console.log(message);
-                        const uriFolder: vscode.Uri = vscode.workspace.workspaceFolders[0].uri;
-                        const uriFile: vscode.Uri = vscode.Uri.file(path.join(uriFolder.path, message.relativePath));
-                        fs.writeFile(uriFile.fsPath, message.yaml, err => {
-                            if (err) vscode.window.showErrorMessage("Error: " + err?.message);
-                        });
-                    }
-                    break;
-                case 'getData':
-                    sendData(context, panel, filename, relativePath, yaml);
-                    break;
-            }
-        },
-        undefined,
-        context.subscriptions
-    );
-    KARAVAN_PANELS.set(relativePath, panel);
-    vscode.commands.executeCommand("setContext", KARAVAN_LOADED, true);
-}
-
-function sendData(context: vscode.ExtensionContext, panel: vscode.WebviewPanel, filename: string, relativePath: string, yaml?: string){
 
-    // Read and send Kamelets
-    console.log("Kamelets sent");
-    panel.webview.postMessage({ command: 'kamelets', kamelets: readKamelets(context) });
+    // Register views
+    const rootPath = (vscode.workspace.workspaceFolders && (vscode.workspace.workspaceFolders.length > 0))
+		? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined;
 
-    // Read and send Components
-    console.log("Components sent");
-    panel.webview.postMessage({ command: 'components', components: readComponents(context) });
+    const integrationView = new IntegrationView(designer, rootPath);
+	vscode.window.registerTreeDataProvider('integrations', integrationView);    
+    vscode.commands.registerCommand('integrations.refresh', () => integrationView.refresh());
 
-    // Send integration
-    panel.webview.postMessage({ command: 'open', filename: filename, relativePath: relativePath, yaml: yaml });
-}
-
-function createIntegration(context: vscode.ExtensionContext, webviewContent: string, crd: boolean) {
-    vscode.window
-        .showInputBox({
-            title: crd ? "Create Camel-K Integration CRD" : "Create Camel Integration YAML",
-            ignoreFocusOut: true,
-            prompt: "Integration name",
-            validateInput: (text: string): string | undefined => {
-                if (!text || text.length === 0) {
-                    return 'Name should not be empty';
-                } else {
-                    return undefined;
-                }
-            }
-        }).then(value => {
-            if (value) {
-                const name = nameFromTitle(value);
-                const i = Integration.createNew(name);
-                i.crd = crd;
-                const yaml = CamelDefinitionYaml.integrationToYaml(i);
-                const filename = name.toLocaleLowerCase().endsWith('.yaml') ? name : name + '.yaml';
-                openKaravanWebView(context, webviewContent, filename, filename, yaml);
-            }
-        });
-}
-
-function getRalativePath(fullPath: string): string {
-    const root = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.path : "";
-    const relativePath = path.resolve(fullPath).replace( path.resolve(root) + path.sep, '');
-    return relativePath;
-}
+    const kameletView = new KameletView(context, rootPath);
+	vscode.window.registerTreeDataProvider('kamelets', kameletView);    
+    vscode.commands.registerCommand('kamelets.refresh', () => kameletView.refresh());
 
-function readKamelets(context: vscode.ExtensionContext): string[] {
-    const dir = path.join(context.extensionPath, 'kamelets');
-    const yamls: string[] = fs.readdirSync(dir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(dir + "/" + file, 'utf-8'));
-    try {
-        const kameletsPath: string = vscode.workspace.getConfiguration().get("Karavan.kameletsPath") || '';
-        const kameletsDir = path.isAbsolute(kameletsPath) ? kameletsPath : path.resolve(kameletsPath);
-        const customKamelets: string[] = fs.readdirSync(kameletsDir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(kameletsDir + "/" + file, 'utf-8'));
-        if (customKamelets && customKamelets.length > 0) yamls.push(...customKamelets);
-    } catch (e) {
-
-    }
-    return yamls;
-}
-
-function readComponents(context: vscode.ExtensionContext): string[] {
-    const dir = path.join(context.extensionPath, 'components');
-    const jsons: string[] = fs.readdirSync(dir).filter(file => file.endsWith("json")).map(file => fs.readFileSync(dir + "/" + file, 'utf-8'));
-    return jsons;
-}
-
-function parceYaml(filename: string, yaml: string): [boolean, string?] {
-    const i = CamelDefinitionYaml.yamlToIntegration(filename, yaml);
-    if (i.kind === 'Integration' && i.metadata.name) {
-        return [true, yaml];
-    } else {
-        return [false, undefined];
-    }
-}
-
-function runCamelJbang(filename: string) {
-    const version = vscode.workspace.getConfiguration().get("camel.version");
-    const maxMessages:number = vscode.workspace.getConfiguration().get("camel.maxMessages") || -1;
-    const loggingLevel = vscode.workspace.getConfiguration().get("camel.loggingLevel");
-    const reload = vscode.workspace.getConfiguration().get("camel.reload");
-    const health = vscode.workspace.getConfiguration().get("camel.health");
-    const messageTracing = vscode.workspace.getConfiguration().get("camel.messageTracing");
-    const command = "jbang -Dcamel.jbang.version=" + version + " camel@apache/camel run " 
-        + toCliFilename(filename)
-        + (maxMessages > -1 ? " --max-messages=" + maxMessages : "")
-        + " --logging-level=" + loggingLevel
-        + (messageTracing ? " --trace" : "")
-        + (reload ? " --reload" : "")
-        + (health ? " --health" : "");
-    const existTerminal = TERMINALS.get(filename);
-    if (existTerminal) existTerminal.dispose();
-    const terminal = vscode.window.createTerminal('Camel: ' + filename);
-    TERMINALS.set(filename, terminal);
-    terminal.show();
-    terminal.sendText(command);
-}
-
-function toCliFilename(filename: string): string {
-    return (/\s/).test(filename)
-        ? '"' + filename + '"'
-        : filename.replace(/\s/g, "\\ ");
-}
+    const componentView = new ComponentView(context, rootPath);
+	vscode.window.registerTreeDataProvider('components', componentView);    
+    vscode.commands.registerCommand('components.refresh', () => componentView.refresh());
 
-function nameFromTitle(title: string): string {
-    return title.replace(/[^a-z0-9+]+/gi, "-").toLowerCase();
+    const dslView = new DslView(context, rootPath);
+	vscode.window.registerTreeDataProvider('dsl', dslView);    
+    vscode.commands.registerCommand('dsl.refresh', () => dslView.refresh());
 }
 
 export function deactivate() {
diff --git a/karavan-vscode/src/integrationView.ts b/karavan-vscode/src/integrationView.ts
new file mode 100644
index 0000000..9c0031c
--- /dev/null
+++ b/karavan-vscode/src/integrationView.ts
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as path from "path";
+import * as utils from "./utils";
+import * as fs from "fs";
+import { CamelDefinitionYaml } from "karavan-core/lib/api/CamelDefinitionYaml";
+import { DesignerView } from "./designerView";
+
+export class IntegrationView implements vscode.TreeDataProvider<IntegrationItem> {
+
+    constructor(private designer: DesignerView, private rootPath: string | undefined) {
+
+    }
+	private _onDidChangeTreeData: vscode.EventEmitter<IntegrationItem | undefined | void> = new vscode.EventEmitter<IntegrationItem | undefined | void>();
+	readonly onDidChangeTreeData: vscode.Event<IntegrationItem | undefined | void> = this._onDidChangeTreeData.event;
+
+	getTreeItem(element: IntegrationItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
+		return element;
+	}
+	getChildren(element?: IntegrationItem): vscode.ProviderResult<IntegrationItem[]> {
+		const integrations: IntegrationItem[] = [];
+		if (this.rootPath){
+			utils.getYamlFiles(this.rootPath).forEach(f => {
+				const yaml = fs.readFileSync(path.resolve(f)).toString('utf8');
+        		if (!f.startsWith(this.rootPath + path.sep + "target") && CamelDefinitionYaml.yamlIsIntegration(yaml)) {
+					const filename = path.basename(f);
+					const i = CamelDefinitionYaml.yamlToIntegration(filename, yaml);
+					integrations.push(new IntegrationItem(i.metadata.name, f, i.crd, {command: 'karavan.open', title:'', arguments: [{fsPath: f}]}));
+				}
+			})
+		}
+		return Promise.resolve(integrations);
+	}
+
+	refresh(): void {
+		this._onDidChangeTreeData.fire();
+	}
+}
+
+export class IntegrationItem extends vscode.TreeItem {
+
+	constructor(
+		public readonly title: string,
+		private readonly fullPath: string,
+		private readonly crd: boolean,
+		public readonly command?: vscode.Command
+	) {
+		super(title, vscode.TreeItemCollapsibleState.None);
+
+		this.tooltip = this.fullPath;
+		this.description = this.crd ? "CRD" : "";
+	}
+
+	iconPath = {
+		light: path.join(__filename, '..', '..', 'icons', 'light', this.crd ? 'crd.svg' : 'karavan.svg'),
+		dark: path.join(__filename, '..', '..', 'icons', 'dark', this.crd ? 'crd.svg' : 'karavan.svg')
+	};
+
+	contextValue = 'integration';
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/kameletView.ts b/karavan-vscode/src/kameletView.ts
new file mode 100644
index 0000000..c1e3ab6
--- /dev/null
+++ b/karavan-vscode/src/kameletView.ts
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as path from "path";
+import * as utils from "./utils";
+import * as fs from "fs";
+import { KameletApi } from "karavan-core/lib/api/KameletApi";
+import { KameletModel } from "karavan-core/lib/model/KameletModels";
+import { ThemeIcon } from "vscode";
+
+export class KameletView implements vscode.TreeDataProvider<KameletItem> {
+
+    constructor(private context: vscode.ExtensionContext, private rootPath: string | undefined) {
+
+    }
+	private _onDidChangeTreeData: vscode.EventEmitter<KameletItem | undefined | void> = new vscode.EventEmitter<KameletItem | undefined | void>();
+	readonly onDidChangeTreeData: vscode.Event<KameletItem | undefined | void> = this._onDidChangeTreeData.event;
+
+	getTreeItem(element: KameletItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
+		return element;
+	}
+	getChildren(element?: KameletItem): vscode.ProviderResult<KameletItem[]> {
+		const kamelets: KameletItem[] = [];
+		if (this.rootPath){
+			utils.readKamelets(this.context).forEach(s => {
+				const k:KameletModel = KameletApi.yamlToKamelet(s);
+				kamelets.push(new KameletItem(k.spec.definition.title, k.spec.definition.description, k.type()));
+			})
+		}
+		return Promise.resolve(kamelets);
+	}
+
+	refresh(): void {
+		this._onDidChangeTreeData.fire();
+	}
+}
+
+export class KameletItem extends vscode.TreeItem {
+
+	constructor(
+		public readonly title: string,
+		public readonly description: string,
+		private readonly type: string,
+		public readonly command?: vscode.Command
+	) {
+		super(title, vscode.TreeItemCollapsibleState.None);
+
+		this.tooltip = this.description;
+		this.description = this.type;
+	}
+
+	iconPath = ThemeIcon.File;
+
+	contextValue = 'kamelet';
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/utils.ts b/karavan-vscode/src/utils.ts
new file mode 100644
index 0000000..6cfd788
--- /dev/null
+++ b/karavan-vscode/src/utils.ts
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as vscode from "vscode";
+import * as fs from "fs";
+import * as path from "path";
+import { CamelDefinitionYaml } from "karavan-core/lib/api/CamelDefinitionYaml";
+
+const TERMINALS: Map<string, vscode.Terminal> = new Map<string, vscode.Terminal>();
+
+
+export function getRalativePath(fullPath: string): string {
+    const root = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.path : "";
+    const relativePath = path.resolve(fullPath).replace(path.resolve(root) + path.sep, '');
+    return relativePath;
+}
+
+export function readKamelets(context: vscode.ExtensionContext): string[] {
+    const dir = path.join(context.extensionPath, 'kamelets');
+    const yamls: string[] = fs.readdirSync(dir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(dir + "/" + file, 'utf-8'));
+    try {
+        const kameletsPath: string = vscode.workspace.getConfiguration().get("Karavan.kameletsPath") || '';
+        const kameletsDir = path.isAbsolute(kameletsPath) ? kameletsPath : path.resolve(kameletsPath);
+        const customKamelets: string[] = fs.readdirSync(kameletsDir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(kameletsDir + "/" + file, 'utf-8'));
+        if (customKamelets && customKamelets.length > 0) yamls.push(...customKamelets);
+    } catch (e) {
+
+    }
+    return yamls;
+}
+
+export function readComponents(context: vscode.ExtensionContext): string[] {
+    const dir = path.join(context.extensionPath, 'components');
+    const jsons: string[] = fs.readdirSync(dir).filter(file => file.endsWith("json")).map(file => fs.readFileSync(dir + "/" + file, 'utf-8'));
+    return jsons;
+}
+
+export function parceYaml(filename: string, yaml: string): [boolean, string?] {
+    const i = CamelDefinitionYaml.yamlToIntegration(filename, yaml);
+    if (i.kind === 'Integration' && i.metadata.name) {
+        return [true, yaml];
+    } else {
+        return [false, undefined];
+    }
+}
+
+export function runCamelJbang(filename: string) {
+    const version = vscode.workspace.getConfiguration().get("camel.version");
+    const maxMessages: number = vscode.workspace.getConfiguration().get("camel.maxMessages") || -1;
+    const loggingLevel = vscode.workspace.getConfiguration().get("camel.loggingLevel");
+    const reload = vscode.workspace.getConfiguration().get("camel.reload");
+    const health = vscode.workspace.getConfiguration().get("camel.health");
+    const messageTracing = vscode.workspace.getConfiguration().get("camel.messageTracing");
+    const command = "jbang -Dcamel.jbang.version=" + version + " camel@apache/camel run "
+        + toCliFilename(filename)
+        + (maxMessages > -1 ? " --max-messages=" + maxMessages : "")
+        + " --logging-level=" + loggingLevel
+        + (messageTracing ? " --trace" : "")
+        + (reload ? " --reload" : "")
+        + (health ? " --health" : "");
+    const existTerminal = TERMINALS.get(filename);
+    if (existTerminal) existTerminal.dispose();
+    const terminal = vscode.window.createTerminal('Camel: ' + filename);
+    TERMINALS.set(filename, terminal);
+    terminal.show();
+    terminal.sendText(command);
+}
+
+export function toCliFilename(filename: string): string {
+    return (/\s/).test(filename)
+        ? '"' + filename + '"'
+        : filename.replace(/\s/g, "\\ ");
+}
+
+export function nameFromTitle(title: string): string {
+    return title.replace(/[^a-z0-9+]+/gi, "-").toLowerCase();
+}
+
+function getAllFiles (dirPath, arrayOfFiles: string[]): string[]  {
+    const files = fs.readdirSync(dirPath)
+  
+    arrayOfFiles = arrayOfFiles || []
+  
+    files.forEach(function(file) {
+      if (fs.statSync(dirPath + "/" + file).isDirectory()) {
+        arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles)
+      } else {
+        arrayOfFiles.push(path.join(dirPath, "/", file))
+      }
+    })
+    return arrayOfFiles
+  }
+
+export function getYamlFiles(baseDir: string): string[] {
+    const result:string[] = [];
+    getAllFiles(baseDir, []).filter(f => f.endsWith(".yaml")).forEach(f => {
+        result.push(f);
+    })
+    return result;
+}
+
+