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/04/12 14:45:26 UTC

[camel-karavan] branch main updated: EIP, Kamelet, Component catalogs (#303)

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 4056a54  EIP, Kamelet, Component catalogs (#303)
4056a54 is described below

commit 4056a5423542456465776e5393ab8fa25427f793
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Tue Apr 12 10:45:21 2022 -0400

    EIP, Kamelet, Component catalogs (#303)
    
    * Kamelet Catalog
    
    * Kamelet Card Style
    
    * Component Catalog VSCode
    
    * EIP Calatog in VSCode
    
    * Catalogs in Application
---
 karavan-app/src/main/webapp/package.json           |   7 +-
 karavan-app/src/main/webapp/src/Main.tsx           |  22 +++-
 .../main/webapp/src/components/ComponentCard.tsx   |  48 ++++++++
 .../ComponentModal.tsx}                            |  67 ++++++-----
 .../ComponentsPage.tsx}                            |  43 +++----
 karavan-app/src/main/webapp/src/eip/EipCard.tsx    |  46 ++++++++
 .../KameletModal.tsx => eip/EipModal.tsx}          |  60 +++++-----
 .../{kamelets/KameletsPage.tsx => eip/EipPage.tsx} |  44 ++++---
 .../src/main/webapp/src/kamelets/KameletCard.tsx   |  17 +--
 .../src/main/webapp/src/kamelets/KameletModal.tsx  |   2 +-
 .../src/main/webapp/src/kamelets/KameletsPage.tsx  |   9 +-
 karavan-core/package-lock.json                     |   4 +-
 karavan-core/src/core/api/ComponentApi.ts          |   4 +-
 karavan-core/src/core/api/KameletApi.ts            |   3 +-
 karavan-designer/package-lock.json                 | 109 ++++++++++++++----
 karavan-designer/package.json                      |   1 +
 karavan-designer/src/App.tsx                       |  58 +++++-----
 karavan-designer/src/components/ComponentCard.tsx  |  48 ++++++++
 .../src/components/ComponentModal.tsx              |  67 ++++++-----
 .../src/components/ComponentsPage.tsx              |  43 +++----
 karavan-designer/src/designer/karavan.css          |   9 +-
 karavan-designer/src/eip/EipCard.tsx               |  46 ++++++++
 .../src/eip/EipModal.tsx                           |  60 +++++-----
 .../src/eip/EipPage.tsx                            |  44 ++++---
 karavan-designer/src/index.tsx                     |  20 +++-
 .../src/kamelets/KameletCard.tsx                   |  17 +--
 .../src/kamelets/KameletModal.tsx                  |   2 +-
 .../src/kamelets/KameletsPage.tsx                  |   9 +-
 karavan-vscode/package-lock.json                   | 117 +++++++++++++++----
 karavan-vscode/package.json                        |  80 +++++--------
 karavan-vscode/src/componentView.ts                |  70 ------------
 karavan-vscode/src/designerView.ts                 |   2 +-
 karavan-vscode/src/eipView.ts                      |  70 ------------
 karavan-vscode/src/extension.ts                    |  24 ++--
 karavan-vscode/src/helpView.ts                     | 126 +++++++++++++++++++++
 karavan-vscode/src/kameletView.ts                  |  69 -----------
 karavan-vscode/src/utils.ts                        |   3 -
 karavan-vscode/webview/App.tsx                     |  28 ++++-
 .../webview/components/ComponentCard.tsx           |  48 ++++++++
 .../webview/components/ComponentModal.tsx          |  67 ++++++-----
 .../webview/components/ComponentsPage.tsx          |  43 +++----
 karavan-vscode/webview/eip/EipCard.tsx             |  46 ++++++++
 .../webview/eip/EipModal.tsx                       |  60 +++++-----
 .../webview/eip/EipPage.tsx                        |  44 ++++---
 karavan-vscode/webview/index.css                   |  38 +++++++
 .../webview}/kamelets/KameletCard.tsx              |  17 +--
 .../webview}/kamelets/KameletModal.tsx             |   2 +-
 .../webview}/kamelets/KameletsPage.tsx             |   9 +-
 48 files changed, 1160 insertions(+), 712 deletions(-)

diff --git a/karavan-app/src/main/webapp/package.json b/karavan-app/src/main/webapp/package.json
index 82e40cb..d7c065c 100644
--- a/karavan-app/src/main/webapp/package.json
+++ b/karavan-app/src/main/webapp/package.json
@@ -3,9 +3,10 @@
   "version": "0.0.15",
   "private": true,
   "scripts": {
-    "start": "cp -r ../../../../karavan-designer/src/designer src && react-scripts start",
-    "build": "cp -r ../../../../karavan-designer/src/designer src && react-scripts build",
-    "prod": "cp -r ../../../../karavan-designer/src/designer src && react-scripts build --dest && rsync -a build/* ../resources/META-INF/resources"
+    "copy-designer": "cp -r ../../../../karavan-designer/src/designer src && cp -r ../../../../karavan-designer/src/kamelets src && cp -r ../../../../karavan-designer/src/components src && cp -r ../../../../karavan-designer/src/eip src",
+    "start": "npm run copy-designer && react-scripts start",
+    "build": "npm run copy-designer && react-scripts build",
+    "prod": "npm run copy-designer && react-scripts build --dest && rsync -a build/* ../resources/META-INF/resources"
   },
   "proxy": "http://127.0.0.1:8080/",
   "eslintConfig": {
diff --git a/karavan-app/src/main/webapp/src/Main.tsx b/karavan-app/src/main/webapp/src/Main.tsx
index b37d53b..aff65df 100644
--- a/karavan-app/src/main/webapp/src/Main.tsx
+++ b/karavan-app/src/main/webapp/src/Main.tsx
@@ -36,6 +36,8 @@ import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml";
 import avatarImg from './avatarImg.svg';
 import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 import Icon from "./Logo";
+import {ComponentsPage} from "./components/ComponentsPage";
+import {EipPage} from "./eip/EipPage";
 
 class ToastMessage {
     id: string = ''
@@ -58,7 +60,7 @@ interface State {
     version: string,
     mode: 'local' | 'gitops' | 'serverless',
     isNavOpen: boolean,
-    pageId: 'integrations' | 'configuration' | 'kamelets' | 'designer'
+    pageId: 'integrations' | 'configuration' | 'kamelets' | 'designer' | "components" | "eip"
     integrations: Map<string,string>,
     integration: Integration,
     isModalOpen: boolean,
@@ -166,14 +168,22 @@ export class Main extends React.Component<Props, State> {
                      isActive={this.state.pageId === 'integrations'}>
                 Integrations
             </NavItem>
+            <NavItem id="eip" to="#" itemId={"eip"}
+                     isActive={this.state.pageId === 'eip'}>
+                Enterprise Integration Patterns
+            </NavItem>
             <NavItem id="kamelets" to="#" itemId={"kamelets"}
                      isActive={this.state.pageId === 'kamelets'}>
                 Kamelets
             </NavItem>
-            <NavItem id="configuration" to="#" itemId={"configuration"}
-                     isActive={this.state.pageId === 'configuration'}>
-                Configuration
+            <NavItem id="components" to="#" itemId={"components"}
+                     isActive={this.state.pageId === 'components'}>
+                Components
             </NavItem>
+            {/*<NavItem id="configuration" to="#" itemId={"configuration"}*/}
+            {/*         isActive={this.state.pageId === 'configuration'}>*/}
+            {/*    Configuration*/}
+            {/*</NavItem>*/}
         </NavList>
     </Nav>);
 
@@ -237,7 +247,9 @@ export class Main extends React.Component<Props, State> {
                                  onDelete={this.onIntegrationDelete} onSelect={this.onIntegrationSelect}
                                  onCreate={this.onIntegrationCreate}/>}
                 {this.state.pageId === 'configuration' && <ConfigurationPage/>}
-                {this.state.pageId === 'kamelets' && <KameletsPage/>}
+                {this.state.pageId === 'kamelets' && <KameletsPage dark={false}/>}
+                {this.state.pageId === 'components' && <ComponentsPage dark={false}/>}
+                {this.state.pageId === 'eip' && <EipPage dark={false}/>}
                 {this.state.pageId === 'designer' &&
                 <DesignerPage mode={this.state.mode} integration={this.state.integration}/>}
                 <Modal
diff --git a/karavan-app/src/main/webapp/src/components/ComponentCard.tsx b/karavan-app/src/main/webapp/src/components/ComponentCard.tsx
new file mode 100644
index 0000000..e1adb01
--- /dev/null
+++ b/karavan-app/src/main/webapp/src/components/ComponentCard.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardActions, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {KameletModel} from "karavan-core/lib/model/KameletModels";
+import {camelIcon, CamelUi} from "../designer/utils/CamelUi";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+
+interface Props {
+    component: Component,
+    onClickCard: any
+}
+
+interface State {
+    component: Component,
+}
+
+export class ComponentCard extends React.Component<Props, State> {
+
+    public state: State = {
+        component: this.props.component
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.component);
+    }
+
+    render() {
+        const component = this.state.component;
+        return (
+            <Card isHoverable isCompact key={component.component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.component.name)}</CardTitle>
+                <CardBody>{component.component.description}</CardBody>
+                <CardFooter>
+                    <Badge isRead className="labels">{component.component.label}</Badge>
+                    <Badge isRead className="version">{component.component.version}</Badge>
+                </CardFooter>
+            </Card>
+        );
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-app/src/main/webapp/src/components/ComponentModal.tsx
similarity index 51%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-app/src/main/webapp/src/components/ComponentModal.tsx
index 3213a87..25e72cc 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-app/src/main/webapp/src/components/ComponentModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,27 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {camelIcon} from "../designer/utils/CamelUi";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import {ComponentProperty} from "karavan-core/src/core/model/ComponentModels";
 
 interface Props {
-    kamelet?: KameletModel,
+    component?: Component,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    component?: Component,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class ComponentModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        component: this.props.component,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +42,67 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.component;
+        const props = new Map<string, ComponentProperty>();
+        if (component){
+            ComponentApi.getComponentProperties(component?.component.name, "consumer").forEach(cp => props.set(cp.name, cp));
+            ComponentApi.getComponentProperties(component?.component.name, "producer").forEach(cp => props.set(cp.name, cp));
+        }
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.component.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.component.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.component.label}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.component.description}</Text>
+                    {props.size !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {Array.from(props.values()).map((p: ComponentProperty, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +111,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-app/src/main/webapp/src/components/ComponentsPage.tsx
similarity index 54%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-app/src/main/webapp/src/components/ComponentsPage.tsx
index 6b2a251..203a789 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-app/src/main/webapp/src/components/ComponentsPage.tsx
@@ -8,59 +8,62 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {ComponentCard} from "./ComponentCard";
+import {ComponentModal} from "./ComponentModal";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    component?: Component;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    components: Component[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class ComponentsPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        components: [],
         filter: ''
     };
 
     componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
+        this.setState({components: ComponentApi.getComponents()})
     }
 
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (c: Component)=> {
+        this.setState({component: c, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            components:  ComponentApi.getComponents().filter(c => c.component.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const component = this.state.component;
+        const components = this.state.components;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <ComponentModal key={component?.component.name + this.state.isModalOpen.toString()}
+                                isOpen={this.state.isModalOpen} component={component}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Component Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +81,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {components.map(c => (
+                            <ComponentCard key={c.component.name} component={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-app/src/main/webapp/src/eip/EipCard.tsx b/karavan-app/src/main/webapp/src/eip/EipCard.tsx
new file mode 100644
index 0000000..34d745e
--- /dev/null
+++ b/karavan-app/src/main/webapp/src/eip/EipCard.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    element: ElementMeta,
+    onClickCard: any
+}
+
+interface State {
+    element: ElementMeta,
+}
+
+export class EipCard extends React.Component<Props, State> {
+
+    public state: State = {
+        element: this.props.element
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.element);
+    }
+
+    render() {
+        const component = this.state.element;
+        return (
+            <Card isHoverable isCompact key={component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={CamelUi.getIconForName(component.className)} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.title)}</CardTitle>
+                <CardBody>{component.description}</CardBody>
+                <CardFooter>
+                        <Badge isRead className="labels">{component.labels}</Badge>
+                </CardFooter>
+            </Card>
+        )
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-app/src/main/webapp/src/eip/EipModal.tsx
similarity index 57%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-app/src/main/webapp/src/eip/EipModal.tsx
index 3213a87..ea5e325 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-app/src/main/webapp/src/eip/EipModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,25 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta, PropertyMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
-    kamelet?: KameletModel,
+    element?: ElementMeta,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    element?: ElementMeta,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class EipModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        element: this.props.element,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +40,62 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.element;
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={CamelUi.getIconForName(component?.name || '')} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.labels}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.description}</Text>
+                    {component?.properties.length !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {component?.properties.map((p: PropertyMeta, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +104,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-app/src/main/webapp/src/eip/EipPage.tsx
similarity index 56%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-app/src/main/webapp/src/eip/EipPage.tsx
index 6b2a251..fe5fa2f 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-app/src/main/webapp/src/eip/EipPage.tsx
@@ -8,59 +8,57 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {EipCard} from "./EipCard";
+import {EipModal} from "./EipModal";
+import {CamelModelMetadata, ElementMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    element?: ElementMeta;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    elements: ElementMeta[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class EipPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        elements: CamelModelMetadata.sort((a: ElementMeta,b: ElementMeta) => a.name > b.name ? 1 : -1),
         filter: ''
     };
 
-    componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
-    }
-
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (e: ElementMeta)=> {
+        this.setState({element: e, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            elements:  CamelModelMetadata.filter(c => c.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const element = this.state.element;
+        const elements = this.state.elements;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <EipModal key={element?.name + this.state.isModalOpen.toString()}
+                          isOpen={this.state.isModalOpen} element={element}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Enterprise Integration Patterns</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +76,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {elements.map(c => (
+                            <EipCard key={c.name} element={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx b/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
index 8a9cd75..8e05901 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
+++ b/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
@@ -27,20 +27,21 @@ export class KameletCard extends React.Component<Props, State> {
     }
 
     render() {
+        const kamelet = this.state.kamelet;
         return (
-            <Card isHoverable isCompact key={this.state.kamelet.metadata.name} className="kamelet-card"
+            <Card isHoverable isCompact key={kamelet.metadata.name} className="kamelet-card"
                 onClick={event => this.click(event)}
             >
                 <CardHeader>
-                    <img draggable="false" src={this.state.kamelet.icon()} className="kamelet-icon" alt=""></img>
-                    <CardActions>
-                        <Badge className="badge" isRead> {this.state.kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
-                    </CardActions>
+                    <img draggable="false" src={kamelet.icon()} className="kamelet-icon" alt=""></img>
                 </CardHeader>
-                <CardTitle>{CamelUi.titleFromName(this.state.kamelet.metadata.name)}</CardTitle>
-                <CardBody>{this.state.kamelet.spec.definition.description}</CardBody>
+                <CardTitle>{CamelUi.titleFromName(kamelet.metadata.name)}</CardTitle>
+                <CardBody>{kamelet.spec.definition.description}</CardBody>
                 <CardFooter>
-
+                    {/*<div style={{justifyContent: "space-between"}}>*/}
+                        <Badge isRead className="labels">{kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                        <Badge isRead className="version">{kamelet.metadata.annotations["camel.apache.org/catalog.version"].toLowerCase()}</Badge>
+                    {/*</div>*/}
                 </CardFooter>
             </Card>
         );
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
index 3213a87..738c68a 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
@@ -57,7 +57,7 @@ export class KameletModal extends Component<Props, State> {
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
index 6b2a251..a3e0cd4 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
@@ -14,6 +14,7 @@ import {KameletApi} from "karavan-core/lib/api/KameletApi";
 import {KameletModal} from "./KameletModal";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
@@ -53,14 +54,14 @@ export class KameletsPage extends React.Component<Props, State> {
 
     render() {
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
                 <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
                               isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Kamelet Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,7 +79,7 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
                         {this.state.kamelets.map(k => (
                             <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
diff --git a/karavan-core/package-lock.json b/karavan-core/package-lock.json
index 9da3e92..7d049f0 100644
--- a/karavan-core/package-lock.json
+++ b/karavan-core/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "karavan-core",
-  "version": "0.0.14",
+  "version": "0.0.15",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "karavan-core",
-      "version": "0.0.14",
+      "version": "0.0.15",
       "license": "Apache-2.0",
       "dependencies": {
         "@types/js-yaml": "^4.0.5",
diff --git a/karavan-core/src/core/api/ComponentApi.ts b/karavan-core/src/core/api/ComponentApi.ts
index 8cc9e69..76c478d 100644
--- a/karavan-core/src/core/api/ComponentApi.ts
+++ b/karavan-core/src/core/api/ComponentApi.ts
@@ -16,6 +16,7 @@
  */
 import {Component, ComponentProperty} from "../model/ComponentModels";
 import {CamelMetadataApi} from "../model/CamelMetadata";
+import {Kamelets} from "./KameletApi";
 
 export const Components: Component[] = [];
 
@@ -27,7 +28,8 @@ export const ComponentApi = {
         return k;
     },
 
-    saveComponents: (jsons: string[]) => {
+    saveComponents: (jsons: string[], clean: boolean = false) => {
+        if (clean) Components.length = 0;
         const components: Component[] = jsons.map(json => ComponentApi.jsonToComponent(json));
         Components.push(...components);
     },
diff --git a/karavan-core/src/core/api/KameletApi.ts b/karavan-core/src/core/api/KameletApi.ts
index 97fa38d..b60abe9 100644
--- a/karavan-core/src/core/api/KameletApi.ts
+++ b/karavan-core/src/core/api/KameletApi.ts
@@ -75,8 +75,9 @@ export const KameletApi = {
         return KameletApi.jsonToKamelet(JSON.stringify(fromYaml));
     },
 
-    saveKamelets: (kameletYamls: string[]) => {
+    saveKamelets: (kameletYamls: string[], clean: boolean = false) => {
         const kamelets:KameletModel[] = kameletYamls.map(text => KameletApi.yamlToKamelet(text));
+        if (clean) Kamelets.length = 0;
         Kamelets.push(...kamelets.sort((a, b) => {
                 if (a.spec.definition.title.toLowerCase() < b.spec.definition.title.toLowerCase()) {
                     return -1;
diff --git a/karavan-designer/package-lock.json b/karavan-designer/package-lock.json
index 1a548f3..ce538b4 100644
--- a/karavan-designer/package-lock.json
+++ b/karavan-designer/package-lock.json
@@ -1,16 +1,17 @@
 {
   "name": "karavan-designer",
-  "version": "0.0.14",
+  "version": "0.0.15",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "karavan-designer",
-      "version": "0.0.14",
+      "version": "0.0.15",
       "license": "Apache-2.0",
       "dependencies": {
         "@patternfly/patternfly": "4.171.1",
         "@patternfly/react-core": "4.192.7",
+        "@patternfly/react-table": "^4.71.16",
         "@reactour/tour": "^2.10.2",
         "@types/js-yaml": "^4.0.5",
         "@types/uuid": "8.3.4",
@@ -33,7 +34,7 @@
       }
     },
     "../karavan-core": {
-      "version": "0.0.14",
+      "version": "0.0.15",
       "license": "Apache-2.0",
       "dependencies": {
         "@types/js-yaml": "^4.0.5",
@@ -48,6 +49,7 @@
         "@types/mocha": "^9.1.0",
         "@types/node": "^17.0.23",
         "chai": "^4.3.4",
+        "cross-env": "^7.0.3",
         "fs": "^0.0.1-security",
         "mocha": "^9.2.0",
         "ts-node": "^10.4.0"
@@ -2910,23 +2912,58 @@
       }
     },
     "node_modules/@patternfly/react-icons": {
-      "version": "4.49.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.49.5.tgz",
-      "integrity": "sha512-pR04R32KZAd4uPWeFf/pYXp0uUTwDotsM1iPbjJ6Rpl1sELM4LuQV4gaG22dWLy24VCRizFoP6BSzDxmq+GY4g==",
+      "version": "4.53.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.53.16.tgz",
+      "integrity": "sha512-QQOZwl9MR71uNaKUPKJUm2qjvol28evN7GgyiqGn7fr0p4FnPopm9F5GsnKMsE/764/HGwGLjYHulUo3Eb06dQ==",
       "peerDependencies": {
         "react": "^16.8.0 || ^17.0.0",
         "react-dom": "^16.8.0 || ^17.0.0"
       }
     },
     "node_modules/@patternfly/react-styles": {
-      "version": "4.48.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.48.5.tgz",
-      "integrity": "sha512-kXY2piAInTuv1PxuQbSuDYJ+ugIsEs9MnwWqZOMARGrcsElbRLn+vtSxShx7AQeJ9V9e0v64gdgP7pIJqisd1Q=="
+      "version": "4.52.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.52.16.tgz",
+      "integrity": "sha512-i/xj+r0qVlhSoxrFOePxXoC8BudDPsEma0qwP+3Ry4hSZhN6XhSRSqjA5xmaLkgbfWCAiT/+mR9ilCaguxoLTA=="
+    },
+    "node_modules/@patternfly/react-table": {
+      "version": "4.71.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-4.71.16.tgz",
+      "integrity": "sha512-HF//Sk1nnF7phAOjglC8zndRfJ3/3oe8Bkxbufhp3lSFdAyzjed6WBdV2dNIrsNj1UeO8MRSlYCbbDEZZlrO2A==",
+      "dependencies": {
+        "@patternfly/react-core": "^4.202.16",
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "lodash": "^4.17.19",
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@patternfly/react-table/node_modules/@patternfly/react-core": {
+      "version": "4.202.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.202.16.tgz",
+      "integrity": "sha512-yWDf0x+YFFVxm72RC/BUaSOn2UsIirT77qif6DfAWdSODhdxTfaLCeBZ08uWgxJ1YZNCrankj60va+G5L+LVrg==",
+      "dependencies": {
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "focus-trap": "6.2.2",
+        "react-dropzone": "9.0.0",
+        "tippy.js": "5.1.2",
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0"
+      }
     },
     "node_modules/@patternfly/react-tokens": {
-      "version": "4.50.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.50.5.tgz",
-      "integrity": "sha512-u8+f4eevQdVC7w4jmy+ynIB9R7A9NlI2v5L8GMtkWLt3A0S4DBzNbU90MPSVwgfw0XHcvdFQjuK3OaS06M0bxw=="
+      "version": "4.54.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.54.16.tgz",
+      "integrity": "sha512-BBVg40L4gx0Gew2kDdGNxP+EtDwGeBuJwXewKrTjXlCa4uhOOj7TqJ5rxhS4GULfYiYbUGdYe7UMFVb+mKDVVg=="
     },
     "node_modules/@pmmmwh/react-refresh-webpack-plugin": {
       "version": "0.5.4",
@@ -18254,20 +18291,49 @@
       }
     },
     "@patternfly/react-icons": {
-      "version": "4.49.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.49.5.tgz",
-      "integrity": "sha512-pR04R32KZAd4uPWeFf/pYXp0uUTwDotsM1iPbjJ6Rpl1sELM4LuQV4gaG22dWLy24VCRizFoP6BSzDxmq+GY4g==",
+      "version": "4.53.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.53.16.tgz",
+      "integrity": "sha512-QQOZwl9MR71uNaKUPKJUm2qjvol28evN7GgyiqGn7fr0p4FnPopm9F5GsnKMsE/764/HGwGLjYHulUo3Eb06dQ==",
       "requires": {}
     },
     "@patternfly/react-styles": {
-      "version": "4.48.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.48.5.tgz",
-      "integrity": "sha512-kXY2piAInTuv1PxuQbSuDYJ+ugIsEs9MnwWqZOMARGrcsElbRLn+vtSxShx7AQeJ9V9e0v64gdgP7pIJqisd1Q=="
+      "version": "4.52.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.52.16.tgz",
+      "integrity": "sha512-i/xj+r0qVlhSoxrFOePxXoC8BudDPsEma0qwP+3Ry4hSZhN6XhSRSqjA5xmaLkgbfWCAiT/+mR9ilCaguxoLTA=="
+    },
+    "@patternfly/react-table": {
+      "version": "4.71.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-4.71.16.tgz",
+      "integrity": "sha512-HF//Sk1nnF7phAOjglC8zndRfJ3/3oe8Bkxbufhp3lSFdAyzjed6WBdV2dNIrsNj1UeO8MRSlYCbbDEZZlrO2A==",
+      "requires": {
+        "@patternfly/react-core": "^4.202.16",
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "lodash": "^4.17.19",
+        "tslib": "^2.0.0"
+      },
+      "dependencies": {
+        "@patternfly/react-core": {
+          "version": "4.202.16",
+          "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.202.16.tgz",
+          "integrity": "sha512-yWDf0x+YFFVxm72RC/BUaSOn2UsIirT77qif6DfAWdSODhdxTfaLCeBZ08uWgxJ1YZNCrankj60va+G5L+LVrg==",
+          "requires": {
+            "@patternfly/react-icons": "^4.53.16",
+            "@patternfly/react-styles": "^4.52.16",
+            "@patternfly/react-tokens": "^4.54.16",
+            "focus-trap": "6.2.2",
+            "react-dropzone": "9.0.0",
+            "tippy.js": "5.1.2",
+            "tslib": "^2.0.0"
+          }
+        }
+      }
     },
     "@patternfly/react-tokens": {
-      "version": "4.50.5",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.50.5.tgz",
-      "integrity": "sha512-u8+f4eevQdVC7w4jmy+ynIB9R7A9NlI2v5L8GMtkWLt3A0S4DBzNbU90MPSVwgfw0XHcvdFQjuK3OaS06M0bxw=="
+      "version": "4.54.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.54.16.tgz",
+      "integrity": "sha512-BBVg40L4gx0Gew2kDdGNxP+EtDwGeBuJwXewKrTjXlCa4uhOOj7TqJ5rxhS4GULfYiYbUGdYe7UMFVb+mKDVVg=="
     },
     "@pmmmwh/react-refresh-webpack-plugin": {
       "version": "0.5.4",
@@ -24016,6 +24082,7 @@
         "@types/node": "^17.0.23",
         "@types/uuid": "^8.3.4",
         "chai": "^4.3.4",
+        "cross-env": "^7.0.3",
         "fs": "^0.0.1-security",
         "mocha": "^9.2.0",
         "ts-node": "^10.4.0",
diff --git a/karavan-designer/package.json b/karavan-designer/package.json
index 0f10956..4490c5f 100644
--- a/karavan-designer/package.json
+++ b/karavan-designer/package.json
@@ -28,6 +28,7 @@
   "dependencies": {
     "@patternfly/patternfly": "4.171.1",
     "@patternfly/react-core": "4.192.7",
+    "@patternfly/react-table": "^4.71.16",
     "@reactour/tour": "^2.10.2",
     "@types/js-yaml": "^4.0.5",
     "@types/uuid": "8.3.4",
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index e078a66..67426b7 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -21,9 +21,12 @@ import {
 import {KameletApi} from "karavan-core/lib/api/KameletApi";
 import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 import {KaravanDesigner} from "./designer/KaravanDesigner";
-import {TourProvider, useTour} from "@reactour/tour";
+import {KameletsPage} from "./kamelets/KameletsPage";
+import {ComponentsPage} from "./components/ComponentsPage";
+import {EipPage} from "./eip/EipPage";
 
 interface Props {
+    page: "designer" | "kamelets" | "components" | "eip";
 }
 
 interface State {
@@ -38,27 +41,27 @@ class App extends React.Component<Props, State> {
         name: 'demo.yaml',
         key: '',
         yaml:
-            // 'apiVersion: camel.apache.org/v1\n' +
-            // 'kind: Integration\n' +
-            // 'metadata:\n' +
-            // '  name: postman.yaml\n' +
-            // 'spec:\n' +
-            // '  flows:\n' +
-            // '    - route:\n' +
-            // '        from:\n' +
-            // '          uri: direct:post\n' +
-            // '          steps:\n' +
-            // '            - log:\n' +
-            // '                message: \'Received: ${body}\'\n' +
-            // '            - log:\n' +
-            // '                message: \'Received: ${body}\'\n' +
-            // '            - log:\n' +
-            // '                message: \'Received: ${body}\'\n' +
-            // '            - to:\n' +
-            // '                uri: kamelet:kafka-sink\n' +
-            // '                parameters:\n' +
-            // '                  topic: topic1\n' +
-            // '        id: post\n' +
+        // 'apiVersion: camel.apache.org/v1\n' +
+        // 'kind: Integration\n' +
+        // 'metadata:\n' +
+        // '  name: postman.yaml\n' +
+        // 'spec:\n' +
+        // '  flows:\n' +
+        // '    - route:\n' +
+        // '        from:\n' +
+        // '          uri: direct:post\n' +
+        // '          steps:\n' +
+        // '            - log:\n' +
+        // '                message: \'Received: ${body}\'\n' +
+        // '            - log:\n' +
+        // '                message: \'Received: ${body}\'\n' +
+        // '            - log:\n' +
+        // '                message: \'Received: ${body}\'\n' +
+        // '            - to:\n' +
+        // '                uri: kamelet:kafka-sink\n' +
+        // '                parameters:\n' +
+        // '                  topic: topic1\n' +
+        // '        id: post\n' +
             ''
     };
 
@@ -112,10 +115,13 @@ class App extends React.Component<Props, State> {
     public render() {
         return (
             <Page className="karavan">
-                <KaravanDesigner key={this.state.key} filename={this.state.name} yaml={this.state.yaml}
-                                 onSave={(filename, yaml, propertyOnly) => this.save(filename, yaml, propertyOnly)}
-                                 dark={document.body.className.includes('vscode-dark')}
-                 showStartHelp={true}/>
+                {this.props.page === "designer" && <KaravanDesigner key={this.state.key} filename={this.state.name} yaml={this.state.yaml}
+                                                                    onSave={(filename, yaml, propertyOnly) => this.save(filename, yaml, propertyOnly)}
+                                                                    dark={document.body.className.includes('vscode-dark')}
+                                                                    showStartHelp={true}/>}
+                {this.props.page === "kamelets" && <KameletsPage dark={document.body.className.includes('vscode-dark')} />}
+                {this.props.page === "components" && <ComponentsPage dark={document.body.className.includes('vscode-dark')} />}
+                {this.props.page === "eip" && <EipPage dark={document.body.className.includes('vscode-dark')} />}
             </Page>
         );
     }
diff --git a/karavan-designer/src/components/ComponentCard.tsx b/karavan-designer/src/components/ComponentCard.tsx
new file mode 100644
index 0000000..e1adb01
--- /dev/null
+++ b/karavan-designer/src/components/ComponentCard.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardActions, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {KameletModel} from "karavan-core/lib/model/KameletModels";
+import {camelIcon, CamelUi} from "../designer/utils/CamelUi";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+
+interface Props {
+    component: Component,
+    onClickCard: any
+}
+
+interface State {
+    component: Component,
+}
+
+export class ComponentCard extends React.Component<Props, State> {
+
+    public state: State = {
+        component: this.props.component
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.component);
+    }
+
+    render() {
+        const component = this.state.component;
+        return (
+            <Card isHoverable isCompact key={component.component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.component.name)}</CardTitle>
+                <CardBody>{component.component.description}</CardBody>
+                <CardFooter>
+                    <Badge isRead className="labels">{component.component.label}</Badge>
+                    <Badge isRead className="version">{component.component.version}</Badge>
+                </CardFooter>
+            </Card>
+        );
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-designer/src/components/ComponentModal.tsx
similarity index 51%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-designer/src/components/ComponentModal.tsx
index 3213a87..25e72cc 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-designer/src/components/ComponentModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,27 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {camelIcon} from "../designer/utils/CamelUi";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import {ComponentProperty} from "karavan-core/src/core/model/ComponentModels";
 
 interface Props {
-    kamelet?: KameletModel,
+    component?: Component,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    component?: Component,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class ComponentModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        component: this.props.component,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +42,67 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.component;
+        const props = new Map<string, ComponentProperty>();
+        if (component){
+            ComponentApi.getComponentProperties(component?.component.name, "consumer").forEach(cp => props.set(cp.name, cp));
+            ComponentApi.getComponentProperties(component?.component.name, "producer").forEach(cp => props.set(cp.name, cp));
+        }
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.component.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.component.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.component.label}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.component.description}</Text>
+                    {props.size !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {Array.from(props.values()).map((p: ComponentProperty, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +111,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-designer/src/components/ComponentsPage.tsx
similarity index 54%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-designer/src/components/ComponentsPage.tsx
index 6b2a251..203a789 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-designer/src/components/ComponentsPage.tsx
@@ -8,59 +8,62 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {ComponentCard} from "./ComponentCard";
+import {ComponentModal} from "./ComponentModal";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    component?: Component;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    components: Component[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class ComponentsPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        components: [],
         filter: ''
     };
 
     componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
+        this.setState({components: ComponentApi.getComponents()})
     }
 
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (c: Component)=> {
+        this.setState({component: c, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            components:  ComponentApi.getComponents().filter(c => c.component.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const component = this.state.component;
+        const components = this.state.components;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <ComponentModal key={component?.component.name + this.state.isModalOpen.toString()}
+                                isOpen={this.state.isModalOpen} component={component}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Component Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +81,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {components.map(c => (
+                            <ComponentCard key={c.component.name} component={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css
index a5f2beb..88c7730 100644
--- a/karavan-designer/src/designer/karavan.css
+++ b/karavan-designer/src/designer/karavan.css
@@ -1081,4 +1081,11 @@ reactour-portal .reactour__popover button {
 }
 reactour-portal .reactour__popover button:focus-visible {
     outline: none;
-}
\ No newline at end of file
+}
+
+/*Kamelets*/
+.karavan .kamelets-page .kamelet-card .pf-c-card__footer {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+}
diff --git a/karavan-designer/src/eip/EipCard.tsx b/karavan-designer/src/eip/EipCard.tsx
new file mode 100644
index 0000000..34d745e
--- /dev/null
+++ b/karavan-designer/src/eip/EipCard.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    element: ElementMeta,
+    onClickCard: any
+}
+
+interface State {
+    element: ElementMeta,
+}
+
+export class EipCard extends React.Component<Props, State> {
+
+    public state: State = {
+        element: this.props.element
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.element);
+    }
+
+    render() {
+        const component = this.state.element;
+        return (
+            <Card isHoverable isCompact key={component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={CamelUi.getIconForName(component.className)} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.title)}</CardTitle>
+                <CardBody>{component.description}</CardBody>
+                <CardFooter>
+                        <Badge isRead className="labels">{component.labels}</Badge>
+                </CardFooter>
+            </Card>
+        )
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-designer/src/eip/EipModal.tsx
similarity index 57%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-designer/src/eip/EipModal.tsx
index 3213a87..ea5e325 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-designer/src/eip/EipModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,25 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta, PropertyMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
-    kamelet?: KameletModel,
+    element?: ElementMeta,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    element?: ElementMeta,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class EipModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        element: this.props.element,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +40,62 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.element;
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={CamelUi.getIconForName(component?.name || '')} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.labels}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.description}</Text>
+                    {component?.properties.length !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {component?.properties.map((p: PropertyMeta, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +104,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-designer/src/eip/EipPage.tsx
similarity index 56%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-designer/src/eip/EipPage.tsx
index 6b2a251..fe5fa2f 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-designer/src/eip/EipPage.tsx
@@ -8,59 +8,57 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {EipCard} from "./EipCard";
+import {EipModal} from "./EipModal";
+import {CamelModelMetadata, ElementMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    element?: ElementMeta;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    elements: ElementMeta[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class EipPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        elements: CamelModelMetadata.sort((a: ElementMeta,b: ElementMeta) => a.name > b.name ? 1 : -1),
         filter: ''
     };
 
-    componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
-    }
-
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (e: ElementMeta)=> {
+        this.setState({element: e, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            elements:  CamelModelMetadata.filter(c => c.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const element = this.state.element;
+        const elements = this.state.elements;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <EipModal key={element?.name + this.state.isModalOpen.toString()}
+                          isOpen={this.state.isModalOpen} element={element}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Enterprise Integration Patterns</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +76,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {elements.map(c => (
+                            <EipCard key={c.name} element={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-designer/src/index.tsx b/karavan-designer/src/index.tsx
index 19b4ba3..a39991f 100644
--- a/karavan-designer/src/index.tsx
+++ b/karavan-designer/src/index.tsx
@@ -15,9 +15,25 @@
  * limitations under the License.
  */
 import * as React from "react";
-import * as ReactDOM from "react-dom";
 import "./index.css";
 import "@patternfly/patternfly/patternfly.css";
 import App from "./App";
+import {render} from "react-dom";
+import {
+    BrowserRouter,
+    Routes,
+    Route,
+} from "react-router-dom";
 
-ReactDOM.render(<App />, document.getElementById("root") as HTMLElement);
+const rootElement = document.getElementById("root");
+render(
+    <BrowserRouter>
+        <Routes>
+            <Route path="/" element={<App page="designer"/>} />
+            <Route path="kamelets-page" element={<App page="kamelets"/>} />
+            <Route path="components-page" element={<App page="components"/>} />
+            <Route path="eip-page" element={<App page="eip"/>} />
+        </Routes>
+    </BrowserRouter>,
+    rootElement
+);
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx b/karavan-designer/src/kamelets/KameletCard.tsx
similarity index 54%
copy from karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
copy to karavan-designer/src/kamelets/KameletCard.tsx
index 8a9cd75..8e05901 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
+++ b/karavan-designer/src/kamelets/KameletCard.tsx
@@ -27,20 +27,21 @@ export class KameletCard extends React.Component<Props, State> {
     }
 
     render() {
+        const kamelet = this.state.kamelet;
         return (
-            <Card isHoverable isCompact key={this.state.kamelet.metadata.name} className="kamelet-card"
+            <Card isHoverable isCompact key={kamelet.metadata.name} className="kamelet-card"
                 onClick={event => this.click(event)}
             >
                 <CardHeader>
-                    <img draggable="false" src={this.state.kamelet.icon()} className="kamelet-icon" alt=""></img>
-                    <CardActions>
-                        <Badge className="badge" isRead> {this.state.kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
-                    </CardActions>
+                    <img draggable="false" src={kamelet.icon()} className="kamelet-icon" alt=""></img>
                 </CardHeader>
-                <CardTitle>{CamelUi.titleFromName(this.state.kamelet.metadata.name)}</CardTitle>
-                <CardBody>{this.state.kamelet.spec.definition.description}</CardBody>
+                <CardTitle>{CamelUi.titleFromName(kamelet.metadata.name)}</CardTitle>
+                <CardBody>{kamelet.spec.definition.description}</CardBody>
                 <CardFooter>
-
+                    {/*<div style={{justifyContent: "space-between"}}>*/}
+                        <Badge isRead className="labels">{kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                        <Badge isRead className="version">{kamelet.metadata.annotations["camel.apache.org/catalog.version"].toLowerCase()}</Badge>
+                    {/*</div>*/}
                 </CardFooter>
             </Card>
         );
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-designer/src/kamelets/KameletModal.tsx
similarity index 98%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-designer/src/kamelets/KameletModal.tsx
index 3213a87..738c68a 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-designer/src/kamelets/KameletModal.tsx
@@ -57,7 +57,7 @@ export class KameletModal extends Component<Props, State> {
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-designer/src/kamelets/KameletsPage.tsx
similarity index 84%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-designer/src/kamelets/KameletsPage.tsx
index 6b2a251..a3e0cd4 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-designer/src/kamelets/KameletsPage.tsx
@@ -14,6 +14,7 @@ import {KameletApi} from "karavan-core/lib/api/KameletApi";
 import {KameletModal} from "./KameletModal";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
@@ -53,14 +54,14 @@ export class KameletsPage extends React.Component<Props, State> {
 
     render() {
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
                 <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
                               isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Kamelet Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,7 +79,7 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
                         {this.state.kamelets.map(k => (
                             <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
diff --git a/karavan-vscode/package-lock.json b/karavan-vscode/package-lock.json
index 15acf60..d5a82a7 100644
--- a/karavan-vscode/package-lock.json
+++ b/karavan-vscode/package-lock.json
@@ -1,16 +1,17 @@
 {
   "name": "karavan",
-  "version": "0.0.14",
+  "version": "0.0.15",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "karavan",
-      "version": "0.0.14",
+      "version": "0.0.15",
       "license": "Apache-2.0",
       "dependencies": {
         "@patternfly/patternfly": "4.171.1",
         "@patternfly/react-core": "4.192.7",
+        "@patternfly/react-table": "^4.71.16",
         "@reactour/tour": "^2.10.2",
         "@types/js-yaml": "4.0.5",
         "@types/uuid": "8.3.4",
@@ -56,7 +57,7 @@
       }
     },
     "../karavan-core": {
-      "version": "0.0.14",
+      "version": "0.0.15",
       "license": "Apache-2.0",
       "dependencies": {
         "@types/js-yaml": "^4.0.5",
@@ -2058,23 +2059,58 @@
       }
     },
     "node_modules/@patternfly/react-icons": {
-      "version": "4.43.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.43.15.tgz",
-      "integrity": "sha512-b1fcPpIsQVJBGG1onpNTDiGqVJ60BVNy3qvzUu4Ea+lOwP83oIlhODtS792wx1B284a4wxP3uMc6uXCfdULD/w==",
+      "version": "4.53.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.53.16.tgz",
+      "integrity": "sha512-QQOZwl9MR71uNaKUPKJUm2qjvol28evN7GgyiqGn7fr0p4FnPopm9F5GsnKMsE/764/HGwGLjYHulUo3Eb06dQ==",
       "peerDependencies": {
         "react": "^16.8.0 || ^17.0.0",
         "react-dom": "^16.8.0 || ^17.0.0"
       }
     },
     "node_modules/@patternfly/react-styles": {
-      "version": "4.42.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.42.15.tgz",
-      "integrity": "sha512-7E6NmaB3b+OOAqIBlS7nJ74Plq+n76VVTH5zxCyUFkrbjo31TRArwLU2dlO/tZr77Z3MiUjGBcoLLEv0R6BZBg=="
+      "version": "4.52.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.52.16.tgz",
+      "integrity": "sha512-i/xj+r0qVlhSoxrFOePxXoC8BudDPsEma0qwP+3Ry4hSZhN6XhSRSqjA5xmaLkgbfWCAiT/+mR9ilCaguxoLTA=="
+    },
+    "node_modules/@patternfly/react-table": {
+      "version": "4.71.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-4.71.16.tgz",
+      "integrity": "sha512-HF//Sk1nnF7phAOjglC8zndRfJ3/3oe8Bkxbufhp3lSFdAyzjed6WBdV2dNIrsNj1UeO8MRSlYCbbDEZZlrO2A==",
+      "dependencies": {
+        "@patternfly/react-core": "^4.202.16",
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "lodash": "^4.17.19",
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@patternfly/react-table/node_modules/@patternfly/react-core": {
+      "version": "4.202.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.202.16.tgz",
+      "integrity": "sha512-yWDf0x+YFFVxm72RC/BUaSOn2UsIirT77qif6DfAWdSODhdxTfaLCeBZ08uWgxJ1YZNCrankj60va+G5L+LVrg==",
+      "dependencies": {
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "focus-trap": "6.2.2",
+        "react-dropzone": "9.0.0",
+        "tippy.js": "5.1.2",
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0"
+      }
     },
     "node_modules/@patternfly/react-tokens": {
-      "version": "4.44.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.44.15.tgz",
-      "integrity": "sha512-Xp82baZURMISkvpNaWNu3w4cMfc2NIsDYh9K5QpVMQ94vphQrAd54UoO5NQI574+/QY2IPGKWadfvix8324J0Q=="
+      "version": "4.54.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.54.16.tgz",
+      "integrity": "sha512-BBVg40L4gx0Gew2kDdGNxP+EtDwGeBuJwXewKrTjXlCa4uhOOj7TqJ5rxhS4GULfYiYbUGdYe7UMFVb+mKDVVg=="
     },
     "node_modules/@react-aria/focus": {
       "version": "3.5.0",
@@ -5691,6 +5727,11 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
     "node_modules/lodash.assignin": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
@@ -10065,20 +10106,49 @@
       }
     },
     "@patternfly/react-icons": {
-      "version": "4.43.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.43.15.tgz",
-      "integrity": "sha512-b1fcPpIsQVJBGG1onpNTDiGqVJ60BVNy3qvzUu4Ea+lOwP83oIlhODtS792wx1B284a4wxP3uMc6uXCfdULD/w==",
+      "version": "4.53.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.53.16.tgz",
+      "integrity": "sha512-QQOZwl9MR71uNaKUPKJUm2qjvol28evN7GgyiqGn7fr0p4FnPopm9F5GsnKMsE/764/HGwGLjYHulUo3Eb06dQ==",
       "requires": {}
     },
     "@patternfly/react-styles": {
-      "version": "4.42.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.42.15.tgz",
-      "integrity": "sha512-7E6NmaB3b+OOAqIBlS7nJ74Plq+n76VVTH5zxCyUFkrbjo31TRArwLU2dlO/tZr77Z3MiUjGBcoLLEv0R6BZBg=="
+      "version": "4.52.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.52.16.tgz",
+      "integrity": "sha512-i/xj+r0qVlhSoxrFOePxXoC8BudDPsEma0qwP+3Ry4hSZhN6XhSRSqjA5xmaLkgbfWCAiT/+mR9ilCaguxoLTA=="
+    },
+    "@patternfly/react-table": {
+      "version": "4.71.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-4.71.16.tgz",
+      "integrity": "sha512-HF//Sk1nnF7phAOjglC8zndRfJ3/3oe8Bkxbufhp3lSFdAyzjed6WBdV2dNIrsNj1UeO8MRSlYCbbDEZZlrO2A==",
+      "requires": {
+        "@patternfly/react-core": "^4.202.16",
+        "@patternfly/react-icons": "^4.53.16",
+        "@patternfly/react-styles": "^4.52.16",
+        "@patternfly/react-tokens": "^4.54.16",
+        "lodash": "^4.17.19",
+        "tslib": "^2.0.0"
+      },
+      "dependencies": {
+        "@patternfly/react-core": {
+          "version": "4.202.16",
+          "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.202.16.tgz",
+          "integrity": "sha512-yWDf0x+YFFVxm72RC/BUaSOn2UsIirT77qif6DfAWdSODhdxTfaLCeBZ08uWgxJ1YZNCrankj60va+G5L+LVrg==",
+          "requires": {
+            "@patternfly/react-icons": "^4.53.16",
+            "@patternfly/react-styles": "^4.52.16",
+            "@patternfly/react-tokens": "^4.54.16",
+            "focus-trap": "6.2.2",
+            "react-dropzone": "9.0.0",
+            "tippy.js": "5.1.2",
+            "tslib": "^2.0.0"
+          }
+        }
+      }
     },
     "@patternfly/react-tokens": {
-      "version": "4.44.15",
-      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.44.15.tgz",
-      "integrity": "sha512-Xp82baZURMISkvpNaWNu3w4cMfc2NIsDYh9K5QpVMQ94vphQrAd54UoO5NQI574+/QY2IPGKWadfvix8324J0Q=="
+      "version": "4.54.16",
+      "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.54.16.tgz",
+      "integrity": "sha512-BBVg40L4gx0Gew2kDdGNxP+EtDwGeBuJwXewKrTjXlCa4uhOOj7TqJ5rxhS4GULfYiYbUGdYe7UMFVb+mKDVVg=="
     },
     "@react-aria/focus": {
       "version": "3.5.0",
@@ -12755,6 +12825,11 @@
         "p-locate": "^5.0.0"
       }
     },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
     "lodash.assignin": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
diff --git a/karavan-vscode/package.json b/karavan-vscode/package.json
index 2dea45f..86eb137 100644
--- a/karavan-vscode/package.json
+++ b/karavan-vscode/package.json
@@ -47,7 +47,11 @@
     "onCommand:karavan.open",
     "onCommand:karavan.open-yaml",
     "onCommand:karavan.jbang-run",
-    "onView:integrations"
+    "onView:integrations",
+    "onCommand:karavan.openKamelets",
+    "onCommand:karavan.openComponents",
+    "onCommand:karavan.openEip",
+    "onCommand:karavan.reportIssue"
   ],
   "main": "./dist/extension.js",
   "contributes": {
@@ -144,28 +148,20 @@
         }
       },
       {
-        "command": "kamelets.refresh",
-        "title": "Refresh",
-        "icon": {
-          "light": "icons/light/refresh.svg",
-          "dark": "icons/dark/refresh.svg"
-        }
+        "command": "karavan.openKamelets",
+        "title": "Open Kamelet Catalog"
       },
       {
-        "command": "components.refresh",
-        "title": "Refresh",
-        "icon": {
-          "light": "icons/light/refresh.svg",
-          "dark": "icons/dark/refresh.svg"
-        }
+        "command": "karavan.openComponents",
+        "title": "Open Component Catalog"
       },
       {
-        "command": "eip.refresh",
-        "title": "Refresh",
-        "icon": {
-          "light": "icons/light/refresh.svg",
-          "dark": "icons/dark/refresh.svg"
-        }
+        "command": "karavan.openEip",
+        "title": "Open EIP"
+      },
+      {
+        "command": "karavan.reportIssue",
+        "title": "Report Issue"
       }
     ],
     "menus": {
@@ -209,21 +205,6 @@
           "command": "karavan.create-crd",
           "when": "view == integrations",
           "group": "navigation"
-        },
-        {
-          "command": "kamelets.refresh",
-          "when": "view == kamelets",
-          "group": "navigation"
-        },
-        {
-          "command": "components.refresh",
-          "when": "view == components",
-          "group": "navigation"
-        },
-        {
-          "command": "eip.refresh",
-          "when": "view == eip",
-          "group": "navigation"
         }
       ],
       "view/item/context": [
@@ -257,22 +238,13 @@
       "karavanView": [
         {
           "id": "integrations",
-          "name": "Integrations"
-        },
-        {
-          "id": "eip",
-          "name": "Enterprise Integration Patterns",
-          "visibility": "collapsed"
-        },
-        {
-          "id": "kamelets",
-          "name": "Kamelets",
-          "visibility": "collapsed"
+          "name": "Integrations",
+          "visibility": "visible"
         },
         {
-          "id": "components",
-          "name": "Components",
-          "visibility": "collapsed"
+          "id": "help",
+          "name": "Help & Feedback",
+          "visibility": "visible"
         }
       ]
     },
@@ -284,13 +256,14 @@
     ]
   },
   "scripts": {
-    "vscode:prepublish": "cp -r ../karavan-designer/src/designer webview && npm run package",
-    "compile": "cp -r ../karavan-designer/src/designer webview && cross-env NODE_ENV=development webpack --progress",
-    "watch": "cp -r ../karavan-designer/src/designer webview && cross-env NODE_ENV=development webpack --progress --watch",
-    "package": "cp -r ../karavan-designer/src/designer webview  && cross-env NODE_ENV=production webpack --progress",
+    "copy-designer": "cp -r ../karavan-designer/src/designer webview && cp -r ../karavan-designer/src/kamelets webview && cp -r ../karavan-designer/src/components webview && cp -r ../karavan-designer/src/eip webview",
+    "vscode:prepublish": "npm run copy-designer && npm run package",
+    "compile": "npm run copy-designer && cross-env NODE_ENV=development webpack --progress",
+    "watch": "npm run copy-designer && cross-env NODE_ENV=development webpack --progress --watch",
+    "package": "npm run copy-designer  && cross-env NODE_ENV=production webpack --progress",
     "test-compile": "tsc -p ./",
     "test-watch": "tsc -watch -p ./",
-    "pretest": "cp -r ../karavan-designer/src/designer webview && npm run test-compile && npm run lint",
+    "pretest": "npm run copy-designer && npm run test-compile && npm run lint",
     "lint": "eslint src webview --ext .ts,.tsx",
     "lint:fix": "eslint --fix src webview --ext .ts,.tsx",
     "test": "node ./out/test/runTest.js"
@@ -328,6 +301,7 @@
   "dependencies": {
     "@patternfly/patternfly": "4.171.1",
     "@patternfly/react-core": "4.192.7",
+    "@patternfly/react-table": "^4.71.16",
     "@reactour/tour": "^2.10.2",
     "@types/js-yaml": "4.0.5",
     "@types/uuid": "8.3.4",
diff --git a/karavan-vscode/src/componentView.ts b/karavan-vscode/src/componentView.ts
deleted file mode 100644
index 1d45778..0000000
--- a/karavan-vscode/src/componentView.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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
index 0fe96d2..12feb95 100644
--- a/karavan-vscode/src/designerView.ts
+++ b/karavan-vscode/src/designerView.ts
@@ -165,7 +165,7 @@ export class DesignerView {
         }
 
         // Send integration
-        panel.webview.postMessage({ command: 'open', filename: filename, relativePath: relativePath, yaml: yaml });
+        panel.webview.postMessage({ command: 'open', page: "designer", filename: filename, relativePath: relativePath, yaml: yaml });
 
     }
 
diff --git a/karavan-vscode/src/eipView.ts b/karavan-vscode/src/eipView.ts
deleted file mode 100644
index 380c4e3..0000000
--- a/karavan-vscode/src/eipView.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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 EipView implements vscode.TreeDataProvider<EipItem> {
-
-    constructor(private context: vscode.ExtensionContext, private rootPath: string | undefined) {
-
-    }
-	private _onDidChangeTreeData: vscode.EventEmitter<EipItem | undefined | void> = new vscode.EventEmitter<EipItem | undefined | void>();
-	readonly onDidChangeTreeData: vscode.Event<EipItem | undefined | void> = this._onDidChangeTreeData.event;
-
-	getTreeItem(element: EipItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
-		return element;
-	}
-	getChildren(element?: EipItem): vscode.ProviderResult<EipItem[]> {
-		const kamelets: EipItem[] = [];
-		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 EipItem(e.title, e.description, e.labels));
-			})
-		}
-		return Promise.resolve(kamelets);
-	}
-
-	refresh(): void {
-		this._onDidChangeTreeData.fire();
-	}
-}
-
-export class EipItem 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 = 'eip';
-}
\ No newline at end of file
diff --git a/karavan-vscode/src/extension.ts b/karavan-vscode/src/extension.ts
index b1a73bc..a871147 100644
--- a/karavan-vscode/src/extension.ts
+++ b/karavan-vscode/src/extension.ts
@@ -18,9 +18,7 @@ import * as vscode from "vscode";
 import * as fs from "fs";
 import { DesignerView } from "./designerView";
 import {IntegrationView} from "./integrationView";
-import { KameletView } from "./kameletView";
-import { ComponentView } from "./componentView";
-import { EipView } from "./eipView";
+import { HelpView } from "./helpView";
 
 const KARAVAN_LOADED = "karavan:loaded";
 
@@ -80,19 +78,15 @@ export function activate(context: vscode.ExtensionContext) {
 	vscode.window.registerTreeDataProvider('integrations', integrationView);    
     vscode.commands.registerCommand('integrations.refresh', () => integrationView.refresh());
 
-    const kameletView = new KameletView(context, rootPath);
-	vscode.window.registerTreeDataProvider('kamelets', kameletView);    
-    vscode.commands.registerCommand('kamelets.refresh', () => kameletView.refresh());
+    const helpView = new HelpView(context, webviewContent);
+	vscode.window.registerTreeDataProvider('help', helpView);    
+    vscode.commands.registerCommand('karavan.openKamelets', () => helpView.openKaravanWebView("kamelets"));
+    vscode.commands.registerCommand('karavan.openComponents', () => helpView.openKaravanWebView("components"));
+    vscode.commands.registerCommand('karavan.openEip', () => helpView.openKaravanWebView("eip"));
 
-    const componentView = new ComponentView(context, rootPath);
-	vscode.window.registerTreeDataProvider('components', componentView);    
-    vscode.commands.registerCommand('components.refresh', () => componentView.refresh());
-
-    const eipView = new EipView(context, rootPath);
-	vscode.window.registerTreeDataProvider('eip', eipView);    
-    vscode.commands.registerCommand('eip.refresh', () => eipView.refresh());
-
-    // vscode.commands.onDidChangeActiveView
+    vscode.commands.registerCommand('karavan.reportIssue', () => {
+        vscode.commands.executeCommand('vscode.open', vscode.Uri.parse('https://github.com/apache/camel-karavan/issues/new?title=[VS+Code]New+report&template=issue_template.md'));
+    });
 }
 
 export function deactivate() {
diff --git a/karavan-vscode/src/helpView.ts b/karavan-vscode/src/helpView.ts
new file mode 100644
index 0000000..4bf321b
--- /dev/null
+++ b/karavan-vscode/src/helpView.ts
@@ -0,0 +1,126 @@
+/*
+ * 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 { ThemeIcon } from "vscode";
+
+const KARAVAN_PANELS: Map<string, vscode.WebviewPanel> = new Map<string, vscode.WebviewPanel>();
+
+export class HelpView implements vscode.TreeDataProvider<HelpItem> {
+
+	constructor(private context: vscode.ExtensionContext, private webviewContent: string) {
+
+	}
+	private _onDidChangeTreeData: vscode.EventEmitter<HelpItem | undefined | void> = new vscode.EventEmitter<HelpItem | undefined | void>();
+	readonly onDidChangeTreeData: vscode.Event<HelpItem | undefined | void> = this._onDidChangeTreeData.event;
+
+	getTreeItem(element: HelpItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
+		return element;
+	}
+	getChildren(element?: HelpItem): vscode.ProviderResult<HelpItem[]> {
+		const helpItems: HelpItem[] = [];
+		helpItems.push(new HelpItem("Enterprise Integration Patterns", "Enterprise Integration Patterns", "eip", 'combine',  { command: 'karavan.openEip' , title: ''}));
+		helpItems.push(new HelpItem("Kamelet catalog", "Kamelet Catalog", "kamelets", 'extensions', { command: 'karavan.openKamelets', title: '' }));
+		helpItems.push(new HelpItem("Component catalog", "Component Catalog", "component", 'extensions', { command: 'karavan.openComponents', title: '' }));
+		helpItems.push(new HelpItem("Report issue", "Report Issue", "issue", 'comment', { command: 'karavan.reportIssue' , title: ''}));
+		return Promise.resolve(helpItems);
+	}
+
+	refresh(): void {
+		this._onDidChangeTreeData.fire();
+	}
+
+	openKaravanWebView(page: string) {
+		if (!KARAVAN_PANELS.has(page)) {
+			// Karavan webview
+			const panel = vscode.window.createWebviewPanel(
+				"karavan",
+				page.toUpperCase(),
+				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/karavan.svg"
+			);
+
+			// Handle messages from the webview
+			panel.webview.onDidReceiveMessage(
+				message => {
+					switch (message.command) {
+						case 'getData':
+							this.sendData(panel, page);
+							break;
+					}
+				},
+				undefined,
+				this.context.subscriptions
+			);
+			// Handle close event
+			panel.onDidDispose(() => {
+				KARAVAN_PANELS.delete(page);
+			}, null, this.context.subscriptions);
+
+			// Handle reopen
+			panel.onDidChangeViewState((e: vscode.WebviewPanelOnDidChangeViewStateEvent) => {
+				if (e.webviewPanel.active) {
+					e.webviewPanel.webview.postMessage({ command: 'reread' })
+				}
+			});
+
+			KARAVAN_PANELS.set(page, panel);
+		} else {
+			KARAVAN_PANELS.get(page)?.reveal(undefined, true);
+		}
+	}
+
+	sendData(panel: vscode.WebviewPanel, page: string) {
+		// Read and send Kamelets
+		if (page === 'kamelets') panel.webview.postMessage({ command: 'kamelets', kamelets: utils.readKamelets(this.context) });
+
+		// Read and send Components
+		if (page === 'components') panel.webview.postMessage({ command: 'components', components: utils.readComponents(this.context) });
+
+		// Send integration
+		panel.webview.postMessage({ command: 'open', page: page });
+	}
+}
+
+export class HelpItem extends vscode.TreeItem {
+
+	constructor(
+		public readonly title: string,
+		public readonly tooltip: string,
+		public readonly page: string,
+		public readonly icon: string,
+		public readonly command?: vscode.Command
+	) {
+		super(title, vscode.TreeItemCollapsibleState.None);
+		this.tooltip = this.tooltip;
+	}
+
+	iconPath = new ThemeIcon(this.icon);
+
+	contextValue = 'help';
+}
\ No newline at end of file
diff --git a/karavan-vscode/src/kameletView.ts b/karavan-vscode/src/kameletView.ts
deleted file mode 100644
index c1e3ab6..0000000
--- a/karavan-vscode/src/kameletView.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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
index fb83026..f6649fe 100644
--- a/karavan-vscode/src/utils.ts
+++ b/karavan-vscode/src/utils.ts
@@ -68,11 +68,8 @@ export function parceYaml(filename: string, yaml: string): [boolean, string?] {
 }
 
 export function disableStartHelp(){
-    console.log("!!!!    3");
     const config = vscode.workspace.getConfiguration();
-    console.log(config);
     config.update("Karavan.showStartHelp", false);
-    console.log("!!!!    4", vscode.workspace.getConfiguration().get("Karavan.showStartHelp"));
 }
 
 export function runCamelJbang(filename: string) {
diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx
index 2ccb61e..7d070c0 100644
--- a/karavan-vscode/webview/App.tsx
+++ b/karavan-vscode/webview/App.tsx
@@ -22,6 +22,9 @@ import { KaravanDesigner } from "./designer/KaravanDesigner";
 import vscode from "./vscode";
 import { KameletApi } from "karavan-core/lib/api/KameletApi";
 import { ComponentApi } from "karavan-core/lib/api/ComponentApi";
+import { KameletsPage } from "./kamelets/KameletsPage";
+import { ComponentsPage } from "./components/ComponentsPage";
+import { EipPage } from "./eip/EipPage";
 
 interface Props {
   dark: boolean
@@ -37,6 +40,7 @@ interface State {
   scheduledYaml: string
   hasChanges: boolean
   showStartHelp: boolean
+  page: "designer" | "kamelets" | "components" | "eip";
 }
 
 class App extends React.Component<Props, State> {
@@ -49,7 +53,8 @@ class App extends React.Component<Props, State> {
     loaded: false,
     scheduledYaml: '',
     hasChanges: false,
-    showStartHelp: false
+    showStartHelp: false,
+    page: "designer"
   };
 
   saveScheduledChanges = () => {
@@ -73,19 +78,27 @@ class App extends React.Component<Props, State> {
     const message = event.data;
     switch (message.command) {
       case 'kamelets':
-        KameletApi.saveKamelets(message.kamelets);
+        KameletApi.saveKamelets(message.kamelets, true);
         break;
       case 'components':
-        ComponentApi.saveComponents(message.components);
+        ComponentApi.saveComponents(message.components, true);
         break;
       case 'showStartHelp':
           this.setState({showStartHelp: message.showStartHelp});
           break;  
       case 'open':
         if (this.state.filename === '' && this.state.key === '') {
-          this.setState({ filename: message.filename, yaml: message.yaml, scheduledYaml: message.yaml, relativePath: message.relativePath, key: Math.random().toString(), loaded: true });
+          this.setState({ 
+            page: message.page, 
+            filename: message.filename, 
+            yaml: message.yaml, 
+            scheduledYaml: message.yaml, 
+            relativePath: message.relativePath, 
+            key: Math.random().toString(), 
+            loaded: true 
+          });
         }
-        break;
+        break;  
       case 'reread':
         this.setState({ loaded: false, filename: '', key: '' });
         vscode.postMessage({ command: 'getData', reread: true});
@@ -114,7 +127,7 @@ class App extends React.Component<Props, State> {
             <Spinner  className="progress-stepper" isSVG diameter="80px" aria-label="Loading..."/>
           </PageSection>
         }
-        {this.state.loaded &&
+        {this.state.loaded && this.state.page === "designer" &&
           <KaravanDesigner
             showStartHelp={this.state.showStartHelp}
             key={this.state.key}
@@ -124,6 +137,9 @@ class App extends React.Component<Props, State> {
             onDisableHelp={this.disableStartHelp}
             dark={this.props.dark} />
         }
+        {this.state.loaded && this.state.page === "kamelets" && <KameletsPage dark={this.props.dark}/>}
+        {this.state.loaded && this.state.page === "components" && <ComponentsPage dark={this.props.dark}/>}
+        {this.state.loaded && this.state.page === "eip" && <EipPage dark={this.props.dark}/>}
       </Page>
     )
   }
diff --git a/karavan-vscode/webview/components/ComponentCard.tsx b/karavan-vscode/webview/components/ComponentCard.tsx
new file mode 100644
index 0000000..e1adb01
--- /dev/null
+++ b/karavan-vscode/webview/components/ComponentCard.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardActions, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {KameletModel} from "karavan-core/lib/model/KameletModels";
+import {camelIcon, CamelUi} from "../designer/utils/CamelUi";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+
+interface Props {
+    component: Component,
+    onClickCard: any
+}
+
+interface State {
+    component: Component,
+}
+
+export class ComponentCard extends React.Component<Props, State> {
+
+    public state: State = {
+        component: this.props.component
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.component);
+    }
+
+    render() {
+        const component = this.state.component;
+        return (
+            <Card isHoverable isCompact key={component.component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.component.name)}</CardTitle>
+                <CardBody>{component.component.description}</CardBody>
+                <CardFooter>
+                    <Badge isRead className="labels">{component.component.label}</Badge>
+                    <Badge isRead className="version">{component.component.version}</Badge>
+                </CardFooter>
+            </Card>
+        );
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-vscode/webview/components/ComponentModal.tsx
similarity index 51%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-vscode/webview/components/ComponentModal.tsx
index 3213a87..25e72cc 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-vscode/webview/components/ComponentModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,27 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {camelIcon} from "../designer/utils/CamelUi";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import {ComponentProperty} from "karavan-core/src/core/model/ComponentModels";
 
 interface Props {
-    kamelet?: KameletModel,
+    component?: Component,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    component?: Component,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class ComponentModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        component: this.props.component,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +42,67 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.component;
+        const props = new Map<string, ComponentProperty>();
+        if (component){
+            ComponentApi.getComponentProperties(component?.component.name, "consumer").forEach(cp => props.set(cp.name, cp));
+            ComponentApi.getComponentProperties(component?.component.name, "producer").forEach(cp => props.set(cp.name, cp));
+        }
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.component.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.component.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={camelIcon} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.component.label}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.component.description}</Text>
+                    {props.size !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {Array.from(props.values()).map((p: ComponentProperty, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +111,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-vscode/webview/components/ComponentsPage.tsx
similarity index 54%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-vscode/webview/components/ComponentsPage.tsx
index 6b2a251..203a789 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-vscode/webview/components/ComponentsPage.tsx
@@ -8,59 +8,62 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {ComponentCard} from "./ComponentCard";
+import {ComponentModal} from "./ComponentModal";
+import {Component} from "karavan-core/lib/model/ComponentModels";
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    component?: Component;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    components: Component[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class ComponentsPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        components: [],
         filter: ''
     };
 
     componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
+        this.setState({components: ComponentApi.getComponents()})
     }
 
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (c: Component)=> {
+        this.setState({component: c, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            components:  ComponentApi.getComponents().filter(c => c.component.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const component = this.state.component;
+        const components = this.state.components;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <ComponentModal key={component?.component.name + this.state.isModalOpen.toString()}
+                                isOpen={this.state.isModalOpen} component={component}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Component Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +81,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {components.map(c => (
+                            <ComponentCard key={c.component.name} component={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-vscode/webview/eip/EipCard.tsx b/karavan-vscode/webview/eip/EipCard.tsx
new file mode 100644
index 0000000..34d745e
--- /dev/null
+++ b/karavan-vscode/webview/eip/EipCard.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import {
+    CardHeader, Card, CardTitle, CardBody, CardFooter,Badge
+} from '@patternfly/react-core';
+import '../designer/karavan.css';
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    element: ElementMeta,
+    onClickCard: any
+}
+
+interface State {
+    element: ElementMeta,
+}
+
+export class EipCard extends React.Component<Props, State> {
+
+    public state: State = {
+        element: this.props.element
+    };
+
+    click = (event: React.MouseEvent) => {
+        event.stopPropagation()
+        this.props.onClickCard.call(this, this.state.element);
+    }
+
+    render() {
+        const component = this.state.element;
+        return (
+            <Card isHoverable isCompact key={component.name} className="kamelet-card"
+                onClick={event => this.click(event)}
+            >
+                <CardHeader>
+                    <img draggable="false" src={CamelUi.getIconForName(component.className)} className="kamelet-icon" alt=""></img>
+                </CardHeader>
+                <CardTitle>{CamelUi.titleFromName(component.title)}</CardTitle>
+                <CardBody>{component.description}</CardBody>
+                <CardFooter>
+                        <Badge isRead className="labels">{component.labels}</Badge>
+                </CardFooter>
+            </Card>
+        )
+    }
+};
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-vscode/webview/eip/EipModal.tsx
similarity index 57%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-vscode/webview/eip/EipModal.tsx
index 3213a87..ea5e325 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-vscode/webview/eip/EipModal.tsx
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React from 'react';
 import {
     Button,
     Modal,
@@ -9,24 +9,25 @@ import {
     Badge, Flex, CardTitle,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletModel, Property} from "karavan-core/lib/model/KameletModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
+import {CamelUi} from "../designer/utils/CamelUi";
+import {ElementMeta, PropertyMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
-    kamelet?: KameletModel,
+    element?: ElementMeta,
     isOpen: boolean;
 }
 
 interface State {
     isOpen: boolean;
-    kamelet?: KameletModel,
+    element?: ElementMeta,
 }
 
-export class KameletModal extends Component<Props, State> {
+export class EipModal extends  React.Component<Props, State> {
 
     public state: State = {
         isOpen: this.props.isOpen,
-        kamelet: this.props.kamelet,
+        element: this.props.element,
     };
 
     setModalOpen = (open: boolean) => {
@@ -39,61 +40,62 @@ export class KameletModal extends Component<Props, State> {
         }
     }
 
-    getKameletProperties = (properties: any): any[] => {
-        return properties
-            ? Array.from(new Map(Object.entries(properties)), ([name, value]) => (value))
-            : [];
-    }
-
     render() {
+        const component = this.state.element;
         return (
             <Modal
                 aria-label={"Kamelet"}
                 width={'fit-content'}
                 maxLength={200}
-                title={this.state.kamelet?.spec.definition.title}
+                title={component?.title}
                 isOpen={this.state.isOpen}
                 onClose={() => this.setModalOpen(false)}
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
                 ]}
             >
-                <Flex direction={{default: 'column'}} key={this.state.kamelet?.metadata.name}
+                <Flex direction={{default: 'column'}} key={component?.name}
                       className="kamelet-modal-card">
                     <CardHeader>
-                        <img draggable="false" src={this.state.kamelet?.icon()} className="kamelet-icon" alt=""></img>
+                        <img draggable="false" src={CamelUi.getIconForName(component?.name || '')} className="kamelet-icon" alt=""></img>
                         <CardActions>
                             <Badge className="badge"
-                                   isRead> {this.state.kamelet?.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                                   isRead> {component?.labels}</Badge>
                         </CardActions>
                     </CardHeader>
-                    <Text className="description">{this.state.kamelet?.spec.definition.description}</Text>
-                    {this.state.kamelet?.spec.definition.properties && this.state.kamelet?.spec.definition.properties.length !== 0 &&
+                    <Text className="description">{component?.description}</Text>
+                    {component?.properties.length !== 0 &&
                     <div>
                         <CardTitle>Properties</CardTitle>
                         <TableComposable aria-label="Simple table" variant='compact'>
                             <Thead>
                                 <Tr>
-                                    <Th key='title'>Title</Th>
-                                    <Th key='type'>Type</Th>
+                                    <Th key='name'>Display Name / Name</Th>
                                     <Th key='desc'>Description</Th>
-                                    <Th key='format'>Format</Th>
-                                    <Th key='example'>Example</Th>
+                                    <Th key='type'>Type</Th>
+                                    <Th key='label'>Label</Th>
                                 </Tr>
                             </Thead>
                             <Tbody>
-                                {this.getKameletProperties(this.state.kamelet?.spec.definition.properties).map((p: Property, idx: number) => (
+                                {component?.properties.map((p: PropertyMeta, idx: number) => (
                                     <Tr key={idx}>
-                                        <Td key={`${idx}_title`}>{p.title}</Td>
+                                        <Td key={`${idx}_name`}>
+                                            <div>
+                                                <b>{p.displayName}</b>
+                                                <div>{p.name}</div>
+                                            </div>
+                                        </Td>
+                                        <Td key={`${idx}_desc`}><div>
+                                            <div>{p.description}</div>
+                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
+                                        </div></Td>
                                         <Td key={`${idx}_type`}>{p.type}</Td>
-                                        <Td key={`${idx}_desc`}>{p.description}</Td>
-                                        <Td key={`${idx}_format`}>{p.format}</Td>
-                                        <Td key={`${idx}_example`}>{p.example}</Td>
+                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                     </Tr>
                                 ))}
                             </Tbody>
@@ -102,6 +104,6 @@ export class KameletModal extends Component<Props, State> {
                     }
                 </Flex>
             </Modal>
-        );
+        )
     }
 }
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-vscode/webview/eip/EipPage.tsx
similarity index 56%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-vscode/webview/eip/EipPage.tsx
index 6b2a251..fe5fa2f 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-vscode/webview/eip/EipPage.tsx
@@ -8,59 +8,57 @@ import {
     PageSection, TextContent, Text, PageSectionVariants, Flex, FlexItem
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {KameletCard} from "./KameletCard";
-import {KameletModel} from "karavan-core/lib/model/KameletModels";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
-import {KameletModal} from "./KameletModal";
+import {EipCard} from "./EipCard";
+import {EipModal} from "./EipModal";
+import {CamelModelMetadata, ElementMeta} from "karavan-core/lib/model/CamelMetadata";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
-    kamelet?: KameletModel;
+    element?: ElementMeta;
     isModalOpen: boolean;
     repository: string,
     path: string,
-    kamelets: KameletModel[],
+    elements: ElementMeta[],
     filter: string
 }
 
-export class KameletsPage extends React.Component<Props, State> {
+export class EipPage extends React.Component<Props, State> {
 
     public state: State = {
         isModalOpen: false,
         repository: '',
         path: '',
-        kamelets: [],
+        elements: CamelModelMetadata.sort((a: ElementMeta,b: ElementMeta) => a.name > b.name ? 1 : -1),
         filter: ''
     };
 
-    componentDidMount() {
-        this.setState({kamelets: KameletApi.getKamelets()})
-    }
-
-    select = (k: KameletModel)=> {
-        this.setState({kamelet: k, isModalOpen: true})
+    select = (e: ElementMeta)=> {
+        this.setState({element: e, isModalOpen: true})
     }
 
     search(filter: string){
         this.setState({
             filter: filter,
             isModalOpen: false,
-            kamelets: KameletApi.getKamelets().filter(kamelet => kamelet.spec.definition.title.toLowerCase().includes(filter.toLowerCase()))
+            elements:  CamelModelMetadata.filter(c => c.name.toLowerCase().includes(filter.toLowerCase()))
         })
     }
 
     render() {
+        const element = this.state.element;
+        const elements = this.state.elements;
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
-                <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
-                              isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
+                <EipModal key={element?.name + this.state.isModalOpen.toString()}
+                          isOpen={this.state.isModalOpen} element={element}/>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Enterprise Integration Patterns</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,10 +76,10 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
-                        {this.state.kamelets.map(k => (
-                            <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>
+                        {elements.map(c => (
+                            <EipCard key={c.name} element={c} onClickCard={this.select}/>
                         ))}
                     </Gallery>
                 </PageSection>
diff --git a/karavan-vscode/webview/index.css b/karavan-vscode/webview/index.css
index aff3a4b..bfe00cc 100644
--- a/karavan-vscode/webview/index.css
+++ b/karavan-vscode/webview/index.css
@@ -291,3 +291,41 @@ body, :root, #root, .karavan {
 .vscode-dark .reactour__mask {
   color: var(--vscode-input-placeholderForeground);
 }
+
+
+/* Kamelets page */
+
+.vscode-dark .karavan .kamelet-section,
+.vscode-dark .karavan .tools-section,
+.vscode-dark .karavan .tools-section .pf-c-toolbar,
+.vscode-dark .karavan .kamelets-page {
+  background-color: transparent;
+  border: none;
+}
+
+.vscode-dark .karavan .tools-section h1 {
+color: var(--vscode-editor-foreground);
+}
+
+.vscode-dark .karavan .kamelets-page .kamelet-card {
+  background-color: var(--vscode-badge-background);
+}
+
+.vscode-dark .karavan .tools-section .text-field {
+  background-color:  var(--vscode-editor-background);
+  border-color:  var(--vscode-input-foreground);
+  color:  var(--vscode-input-foreground);
+}
+
+.vscode-dark .kamelet-modal-card .pf-c-table {
+  background-color: transparent;
+  color:  var(--vscode-input-foreground);
+}
+
+.vscode-dark .pf-c-table {
+  --pf-c-table--cell--Color:  var(--vscode-input-foreground);
+  color:  var(--vscode-input-foreground);
+}
+
+
+
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx b/karavan-vscode/webview/kamelets/KameletCard.tsx
similarity index 54%
copy from karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
copy to karavan-vscode/webview/kamelets/KameletCard.tsx
index 8a9cd75..8e05901 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletCard.tsx
+++ b/karavan-vscode/webview/kamelets/KameletCard.tsx
@@ -27,20 +27,21 @@ export class KameletCard extends React.Component<Props, State> {
     }
 
     render() {
+        const kamelet = this.state.kamelet;
         return (
-            <Card isHoverable isCompact key={this.state.kamelet.metadata.name} className="kamelet-card"
+            <Card isHoverable isCompact key={kamelet.metadata.name} className="kamelet-card"
                 onClick={event => this.click(event)}
             >
                 <CardHeader>
-                    <img draggable="false" src={this.state.kamelet.icon()} className="kamelet-icon" alt=""></img>
-                    <CardActions>
-                        <Badge className="badge" isRead> {this.state.kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
-                    </CardActions>
+                    <img draggable="false" src={kamelet.icon()} className="kamelet-icon" alt=""></img>
                 </CardHeader>
-                <CardTitle>{CamelUi.titleFromName(this.state.kamelet.metadata.name)}</CardTitle>
-                <CardBody>{this.state.kamelet.spec.definition.description}</CardBody>
+                <CardTitle>{CamelUi.titleFromName(kamelet.metadata.name)}</CardTitle>
+                <CardBody>{kamelet.spec.definition.description}</CardBody>
                 <CardFooter>
-
+                    {/*<div style={{justifyContent: "space-between"}}>*/}
+                        <Badge isRead className="labels">{kamelet.metadata.labels["camel.apache.org/kamelet.type"].toLowerCase()}</Badge>
+                        <Badge isRead className="version">{kamelet.metadata.annotations["camel.apache.org/catalog.version"].toLowerCase()}</Badge>
+                    {/*</div>*/}
                 </CardFooter>
             </Card>
         );
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx b/karavan-vscode/webview/kamelets/KameletModal.tsx
similarity index 98%
copy from karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
copy to karavan-vscode/webview/kamelets/KameletModal.tsx
index 3213a87..738c68a 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletModal.tsx
+++ b/karavan-vscode/webview/kamelets/KameletModal.tsx
@@ -57,7 +57,7 @@ export class KameletModal extends Component<Props, State> {
                 actions={[
                     <div className="modal-footer">
                         <ActionGroup className="deploy-buttons">
-                            <Button key="cancel" variant="secondary"
+                            <Button key="cancel" variant="primary"
                                     onClick={e => this.setModalOpen(false)}>Close</Button>
                         </ActionGroup>
                     </div>
diff --git a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx b/karavan-vscode/webview/kamelets/KameletsPage.tsx
similarity index 84%
copy from karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
copy to karavan-vscode/webview/kamelets/KameletsPage.tsx
index 6b2a251..a3e0cd4 100644
--- a/karavan-app/src/main/webapp/src/kamelets/KameletsPage.tsx
+++ b/karavan-vscode/webview/kamelets/KameletsPage.tsx
@@ -14,6 +14,7 @@ import {KameletApi} from "karavan-core/lib/api/KameletApi";
 import {KameletModal} from "./KameletModal";
 
 interface Props {
+    dark: boolean
 }
 
 interface State {
@@ -53,14 +54,14 @@ export class KameletsPage extends React.Component<Props, State> {
 
     render() {
         return (
-            <PageSection padding={{ default: 'noPadding' }} className="kamelet-section">
+            <PageSection variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light} padding={{ default: 'noPadding' }} className="kamelet-section">
                 <KameletModal key={this.state.kamelet?.metadata.name + this.state.isModalOpen.toString()}
                               isOpen={this.state.isModalOpen} kamelet={this.state.kamelet}/>
-                <PageSection className="tools-section" variant={PageSectionVariants.light}>
+                <PageSection  className="tools-section" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Flex className="tools" justifyContent={{default: 'justifyContentSpaceBetween'}}>
                         <FlexItem>
                             <TextContent>
-                                <Text component="h1">Kamelets</Text>
+                                <Text component="h1">Kamelet Catalog</Text>
                             </TextContent>
                         </FlexItem>
                         <FlexItem>
@@ -78,7 +79,7 @@ export class KameletsPage extends React.Component<Props, State> {
                         </FlexItem>
                     </Flex>
                 </PageSection>
-                <PageSection isFilled className="kamelets-page">
+                <PageSection isFilled className="kamelets-page" variant={this.props.dark ? PageSectionVariants.darker : PageSectionVariants.light}>
                     <Gallery hasGutter>
                         {this.state.kamelets.map(k => (
                             <KameletCard key={k.metadata.name} kamelet={k} onClickCard={this.select}/>