diff --git a/VERSION b/VERSION
index ac39a106c48515b621e90c028ed94c6f71bc03fa..78bc1abd14f2c1f6330989d876c4ee7d5daf7ff6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.9.0
+0.10.0
diff --git a/templates/includes/meet_groups.html.ep b/templates/includes/meet_groups.html.ep
index e5cc2b7bd3ea96211d934ed5b1de5a60803661fb..acf6fce335688c0cbedb3499c027e515edbe9457 100644
--- a/templates/includes/meet_groups.html.ep
+++ b/templates/includes/meet_groups.html.ep
@@ -10,7 +10,7 @@
 </div>
 
 % if ( $roles->{owner}  || $roles->{moderator} ) {
-<div v-effect="searchGroups()">
+<div>
   <label class="form-field__label" for="name"><%=l 'Adding groups' %></label>
   <div class="flex flex-row">
   <input type="text" class="w-full text-input" value="" v-model.lazy="filter['group']" id="search_group" placeholder="<%=l 'INPUT_MEET_ADD_GROUPS_PLACEHOLDER' %>"/>
diff --git a/templates/includes/meet_moderators.html.ep b/templates/includes/meet_moderators.html.ep
index fa3233e254c90658923bd44a9a8c7699167b71aa..dff60fe56661811b63c2ac381686a65a375b9b50 100644
--- a/templates/includes/meet_moderators.html.ep
+++ b/templates/includes/meet_moderators.html.ep
@@ -10,7 +10,7 @@
 </div>
 
 % if ( $roles->{owner} ) {
-<div v-effect="searchUsers('moderator')">
+<div>
   <label class="form-field__label" for="name"><%=l 'Adding moderators' %></label>
   <div class="flex flex-row">
     <input type="text" class="w-full text-input" value="" v-model.lazy="filter['moderator']" id="search_moderator" placeholder="<%=l 'INPUT_MEET_ADD_USERS_PLACEHOLDER' %>"/>
diff --git a/templates/includes/meet_participants.html.ep b/templates/includes/meet_participants.html.ep
index 139012116db35944ab9cd145c08b3d8ea412a0c9..fc126fa4365b77a8b53d100905918130b421608c 100644
--- a/templates/includes/meet_participants.html.ep
+++ b/templates/includes/meet_participants.html.ep
@@ -10,7 +10,7 @@
 </div>
 
 % if ( $roles->{owner}  || $roles->{moderator} ) {
-<div v-effect="searchUsers('participant')">
+<div>
   <label class="form-field__label" for="name"><%=l 'Adding people' %></label>
   <div class="flex flex-row">
     <input type="text" class="w-4/5 text-input text-sm" value="" v-model.lazy="filter['participant']" id="search_participant" placeholder="<%=l 'INPUT_MEET_ADD_USERS_PLACEHOLDER' %>"/>
diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep
index f68051638b15c57f88e86942c48bcb3f8a28f5ad..5f5e8b712309db4722b3a592bda2621830a4a363 100644
--- a/templates/layouts/default.html.ep
+++ b/templates/layouts/default.html.ep
@@ -26,6 +26,8 @@
 % if ( $c->stash->{meet} ) {
   <script src='https://jitsi.pirati.cz/external_api.js'></script>
 % }
+  <script src="https://cdn-unpkg.pirati.cz/vue@2.7.8/dist/vue.min.js"></script>
+  <script src="<%= config->{styleguide} %>js/main.bundle.js"></script>
 </head>
 <body>
 
@@ -80,13 +82,11 @@
 
 <div class="container container--default py-8">
   <section>
-    <main v-scope>
+    <main>
 <%= content %>
     </main>
   </section>
 </div>
 
-<script src="https://cdn-unpkg.pirati.cz/vue@2.7.8/dist/vue.min.js"></script>
-<script src="<%= config->{styleguide} %>js/main.bundle.js"></script>
 </body>
 </html>
diff --git a/templates/meet.html.ep b/templates/meet.html.ep
index d0cabe0ad2b1a8ab3b160553daf95d45e060dca7..7664c68ef6e8199f663f3fa135e63f2034483c71 100644
--- a/templates/meet.html.ep
+++ b/templates/meet.html.ep
@@ -1,4 +1,5 @@
 % layout 'default';
+<div id="App">
 <h1 class="head-alt-md mb-8" v-cloak>{{ meet.name }}</h1>
 
 %= include 'includes/meet'
@@ -11,7 +12,7 @@
 <div @click="active_tab='form'" class="p-4 bg-grey-125" :class="tabClass('form')"><%=l $roles->{owner} ? 'Configuration':'About meet' %></div>
 </div>
 
-<div class="border p-4" v-effect="getMeet()" v-cloak>
+<div class="border p-4" v-cloak>
     <div v-if="active_tab == 'groups'">
 %= include 'includes/meet_groups'
     </div>
@@ -32,9 +33,10 @@
     </div>
 </div>
 
-<script type="module">
-  import { createApp } from 'https://cdn-unpkg.pirati.cz/petite-vue@0.2.2/dist/petite-vue.es.js'
+</div><%# APP %>
+
 
+<script type="module">
   const GROUPS_URL      = '/api/groups';
   const USERS_URL       = '/api/users';
   const MEET_URL        = '/api/meets/<%= stash->{id} %>';
@@ -46,176 +48,181 @@
       "Authorization": "Bearer <%= current_user->{api_token} %>",
   };
 
-  createApp({
+  var app = new Vue({
+    el: '#App',
 
-    meet: {},
+    data: {
+        meet: {},
 
-    active_tab: 'groups',
-    delete_confirm_visible: false,
+        active_tab: 'groups',
+        delete_confirm_visible: false,
 
-    filter: {
-        group: '',
-        participant: '',
-        moderator: '',
-    },
+        filter: {
+            group: '',
+            participant: '',
+            moderator: '',
+        },
 
-    search: {
-        group: '',
-        participant: '',
-        moderator: '',
-    },
+        search: {
+            group: '',
+            participant: '',
+            moderator: '',
+        },
 
-    selected: {
-        group: [],
-        participant: [],
-        moderator: [],
+        selected: {
+            group: [],
+            participant: [],
+            moderator: [],
+        },
     },
 
-    tabClass(id) {
-        if (id == this.active_tab) {
-            return "bg-grey-400 text-white font-bold";
-        }
-        else {
-            return "cursor-pointer";
+    methods: {
+        tabClass: function(id) {
+            if (id == this.active_tab) {
+                return "bg-grey-400 text-white font-bold";
+            }
+            else {
+                return "cursor-pointer";
+
+            }
+        },
+
+        getMeet: function() {
+          fetch(MEET_URL, {
+            headers: API_HEADERS,
+          })
+            .then((res) => res.json())
+            .then(res => {
+                this.meet = res;
+            })
+        },
+
+        searchUsers: function(kind) {
 
-        }
-    },
+            if ( this.filter[kind].length < 2 ) {
+                this.search[kind] = [];
+                return true;
+            }
 
-    getMeet() {
-      fetch(MEET_URL, {
-        headers: API_HEADERS,
-      })
-        .then((res) => res.json())
-        .then(res => {
-            this.meet = res;
-        })
-    },
+            fetch(USERS_URL + '?search=' + this.filter[kind] )
+                .then((res) => res.json())
+                .then(res => {
+                    this.search[kind] = res;
+                })
 
-    searchUsers(kind) {
+        },
 
-        if ( this.filter[kind].length < 2 ) {
-            this.search[kind] = [];
+        searchGroups: function() {
+          if ( this.filter['group'].length < 2 ) {
+            this.search['group'] = [];
             return true;
-        }
+          }
 
-        fetch(USERS_URL + '?search=' + this.filter[kind] )
+          fetch(GROUPS_URL + '?search=' + this.filter['group'] )
             .then((res) => res.json())
             .then(res => {
-                this.search[kind] = res;
+                this.search['group'] = res;
             })
+        },
 
-    },
-
-    searchGroups() {
-      if ( this.filter['group'].length < 2 ) {
-        this.search['group'] = [];
-        return true;
-      }
-
-      fetch(GROUPS_URL + '?search=' + this.filter['group'] )
-        .then((res) => res.json())
-        .then(res => {
-            this.search['group'] = res;
-        })
-    },
 % if ( $roles->{owner} ) {
-
-    updateMeet() {
-      fetch(MEET_URL, {
-        method: "PUT",
-        headers: API_HEADERS,
-        body: JSON.stringify({
-            name:        this.meet.name,
-            description: this.meet.description,
-        }),
-      })
-        .then()
-    },
-
-    deleteMeet() {
-      fetch(MEET_URL, {
-        method: "DELETE",
-        headers: API_HEADERS,
-      })
-        .then( response => {
-            window.location.replace("/");
-        })
-        .catch(() => {
-          this.formError = "<%=l 'ERROR_SERVERSIDE' %>"
-        });
-    },
+        updateMeet: function() {
+          fetch(MEET_URL, {
+            method: "PUT",
+            headers: API_HEADERS,
+            body: JSON.stringify({
+                name:        this.meet.name,
+                description: this.meet.description,
+            }),
+          })
+            .then()
+        },
+
+        deleteMeet: function() {
+          fetch(MEET_URL, {
+            method: "DELETE",
+            headers: API_HEADERS,
+          })
+            .then( response => {
+                window.location.replace("/");
+            })
+            .catch(() => {
+              this.formError = "<%=l 'ERROR_SERVERSIDE' %>"
+            });
+        },
 
 % }
 % if ( $roles->{owner} || $roles->{moderator} ) {
 
-    addUsers(kind) {
-      if ( this.selected[kind].length == 0) {
-        return true;
-      }
-
-      const selected = this.search[kind].filter(item => this.selected[kind].includes(item.id))
-
-      fetch(ADD_USERS_URL, {
-        method: "POST",
-        headers: API_HEADERS,
-        body: JSON.stringify({ users: this.selected[kind], kind: kind }),
-      })
-      .then((response) => {
-        if (response.ok) {
-            this.selected[kind] =[]
-            this.filter[kind] = ''
-            this.getMeet()
-        }
-      })
-    },
-
-    removeUser(id, kind) {
-      fetch(MEET_URL + '/users/' + id, {
-        method: "DELETE",
-        headers: API_HEADERS,
-      })
-      .then((response) => {
-        if (response.ok) {
-            this.getMeet()
-        }
-      })
-    },
-
-
-
-    addGroups() {
-      if ( this.selected['group'].length == 0) {
-        return true;
-      }
-
-      fetch(ADD_GROUPS_URL, {
-        method: "POST",
-        headers: API_HEADERS,
-        body: JSON.stringify({ groups: this.selected['group'] }),
-      })
-      .then((response) => {
-        if (response.ok) {
-            this.selected['group'] =[]
-            this.filter['group'] = ''
-            this.getMeet()
-        }
-      })
-    },
-
-    removeGroup(id) {
-      fetch(MEET_URL + '/groups/' + id, {
-        method: "DELETE",
-        headers: API_HEADERS,
-      })
-      .then((response) => {
-        if (response.ok) {
-            this.getMeet()
-        }
-      })
-    },
-
+        addUsers: function(kind) {
+          if ( this.selected[kind].length == 0) {
+            return true;
+          }
+
+          const selected = this.search[kind].filter(item => this.selected[kind].includes(item.id))
+
+          fetch(ADD_USERS_URL, {
+            method: "POST",
+            headers: API_HEADERS,
+            body: JSON.stringify({ users: this.selected[kind], kind: kind }),
+          })
+          .then((response) => {
+            if (response.ok) {
+                this.selected[kind] =[]
+                this.search[kind] =[]
+                this.filter[kind] = ''
+                this.getMeet()
+            }
+          })
+        },
+
+        removeUser: function(id, kind) {
+          fetch(MEET_URL + '/users/' + id, {
+            method: "DELETE",
+            headers: API_HEADERS,
+          })
+          .then((response) => {
+            if (response.ok) {
+                this.getMeet()
+            }
+          })
+        },
+
+        addGroups: function() {
+          if ( this.selected['group'].length == 0) {
+            return true;
+          }
+
+          fetch(ADD_GROUPS_URL, {
+            method: "POST",
+            headers: API_HEADERS,
+            body: JSON.stringify({ groups: this.selected['group'] }),
+          })
+          .then((response) => {
+            if (response.ok) {
+                this.selected['group'] =[]
+                this.search['group'] =[]
+                this.filter['group'] = ''
+                this.getMeet()
+            }
+          })
+        },
+
+        removeGroup: function(id) {
+          fetch(MEET_URL + '/groups/' + id, {
+            method: "DELETE",
+            headers: API_HEADERS,
+          })
+          .then((response) => {
+            if (response.ok) {
+                this.getMeet()
+            }
+          })
+        },
 % }
+    }
 
-  }).mount()
+  });
 
+  app.getMeet();
 </script>
diff --git a/templates/meets.html.ep b/templates/meets.html.ep
index 8b794fe4579ea19d4dcc0927fda674337ec1235b..b9fdc2ca5089d372ed4ed9918c932fc14cb47ebd 100644
--- a/templates/meets.html.ep
+++ b/templates/meets.html.ep
@@ -1,6 +1,7 @@
 % layout 'default';
+<div id="App">
 
-<div v-effect="fetchData()" class="grid grid-cols-1 md:grid-cols-2 gap-4" v-cloak>
+<div class="grid grid-cols-1 md:grid-cols-2 gap-4" v-cloak>
   <div v-for="meet in meets" class="card elevation-4">
     <div class="card__body">
       <div class="flex justify-between mb-2 border-b border-dotted border-grey-300">
@@ -23,17 +24,18 @@
         </span>
       </div>
 
-    </div>
   </div>
+ </div>
 </div>
 
 % if ( current_user->{permissions}{create} ) {
 <form @submit.prevent="submitForm" v-cloak>
 <div class="card elevation-4 space-y-4 mt-2">
+
  <div class="card__body">
   <div class="grid grid-cols-4 gap-4">
     <div class="form-field col-span-3">
-      <input type="text" name="name" class="text-input form-field__control" value="" placeholder="<%=l 'INPUT_MEET_NAME_PLACEHOLDER' %>" v-model="formData.name" @focus="formError=''" />
+      <input type="text" name="name" class="text-input form-field__control" value="" placeholder="<%=l 'INPUT_MEET_NAME_PLACEHOLDER' %>" v-model="newMeet.name" @focus="formError=''" />
     </div>
     <div class="form-field col-span-1 content-center">
       <button class="btn btn--blue-300 btn--hoveractive text-lg">
@@ -42,13 +44,15 @@
    </div>
   </div>
  </div>
+
  <div  v-if="formError" class="my-4"><span class="alert alert--red-600 alert--faded">{{ formError }}</span></div>
+</div>
 </form>
 % }
 
-<script type="module">
-  import { createApp } from 'https://cdn-unpkg.pirati.cz/petite-vue@0.2.2/dist/petite-vue.es.js'
+</div>
 
+<script type="module">
   const BASE_URL = "/api/meets";
   const API_HEADERS     = {
       "Content-Type": "application/json",
@@ -56,69 +60,66 @@
       "Authorization": "Bearer <%= current_user->{api_token} %>",
   };
 
-//  ws.onmessage = (event) => {
-//    console.log(event.data);
-//    this.formError = event.data;
-//  };
-
-  createApp({
-
-//    ws = new WebSocket('ws://<%= config->{domain} %>/ws/').onmessage = (event) => {
-//    console.log(event.data);
-//    this.formError = event.data;
-//  };
+  var app = new Vue({
+    el: '#App',
 
+    data: {
+        meets: [],
+        newMeet: {
+          name: ""
+        },
 
-    meets: [],
-
-    formError: '',
-
-    formData: {
-      name: ""
+        formError: '',
     },
 
-    fetchData() { //TODO: async
-      fetch(BASE_URL, {
-        headers: API_HEADERS,
-      })
-        .then((res) => res.json())
-        .then(res => {
-            this.meets = res.records;
-        })
-    },
+    methods: {
+        fetchData: function() { //TODO: async
+          fetch(BASE_URL, {
+            headers: API_HEADERS,
+          })
+            .then((res) => res.json())
+            .then(res => {
+                this.meets = res.records;
+            })
+        },
 
 % if ( current_user->{permissions}{create} ) {
-    submitForm() {
-      if ( ! this.formData.name.length ) {
-        this.formError = "<%=l 'ERROR_MEET_NAME_REQURED' %>";
-        return true;
-      }
-
-      this.formMessage = "";
-
-      fetch(BASE_URL, {
-        method: "POST",
-        headers: API_HEADERS,
-        body: JSON.stringify(this.formData),
-      })
-        .then( response => {
-          if ( response.status == 201 ) {
-            this.formData.name = ""
-            this.fetchData();
+
+        submitForm: function() {
+          if ( ! this.newMeet.name.length ) {
+            this.formError = "<%=l 'ERROR_MEET_NAME_REQURED' %>";
+            return true;
           }
-          else {
-            response.json().then(json => {
-                this.formError = json.errors[0]['message']
+
+          this.formMessage = "";
+
+          fetch(BASE_URL, {
+            method: "POST",
+            headers: API_HEADERS,
+            body: JSON.stringify(this.newMeet),
+          })
+            .then( response => {
+              if ( response.status == 201 ) {
+                this.newMeet.name = ""
+                this.fetchData();
+              }
+              else {
+                response.json().then(json => {
+                    this.formError = json.errors[0]['message']
+                })
+              }
             })
-          }
-        })
-        .catch(() => {
-          this.formError = "<%=l 'ERROR_SERVERSIDE' %>"
-        });
-    },
+            .catch(() => {
+              this.formError = "<%=l 'ERROR_SERVERSIDE' %>"
+            });
+        },
 
 % }
 
-  }).mount()
 
+    }
+
+  });
+
+  app.fetchData();
 </script>