diff --git a/tools/templates/RiotXFeature/globals.xml.ftl b/tools/templates/RiotXFeature/globals.xml.ftl
new file mode 100644
index 0000000000..7cafd80483
--- /dev/null
+++ b/tools/templates/RiotXFeature/globals.xml.ftl
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<globals>
+    <#include "root://activities/common/common_globals.xml.ftl" />
+    <global id="resOut" value="${resDir}" />
+    <global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
+</globals>
diff --git a/tools/templates/RiotXFeature/recipe.xml.ftl b/tools/templates/RiotXFeature/recipe.xml.ftl
new file mode 100644
index 0000000000..88160fd0f3
--- /dev/null
+++ b/tools/templates/RiotXFeature/recipe.xml.ftl
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<#import "root://activities/common/kotlin_macros.ftl" as kt>
+<recipe>
+	  
+    <instantiate from="root/res/layout/fragment.xml.ftl"
+                   to="${escapeXmlAttribute(resOut)}/layout/${escapeXmlAttribute(fragmentLayout)}.xml" />
+    <open file="${escapeXmlAttribute(resOut)}/layout/${fragmentLayout}.xml" />
+
+	<#if createActivity>
+    <instantiate from="root/src/app_package/Activity.kt.ftl"
+                   to="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />
+	<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />
+	</#if>
+
+    <instantiate from="root/src/app_package/Fragment.kt.ftl"
+                   to="${escapeXmlAttribute(srcOut)}/${fragmentClass}.kt" />			   
+    <open file="${escapeXmlAttribute(srcOut)}/${fragmentClass}.kt" />
+	
+    <instantiate from="root/src/app_package/ViewModel.kt.ftl"
+                   to="${escapeXmlAttribute(srcOut)}/${viewModelClass}.kt" />
+    <open file="${escapeXmlAttribute(srcOut)}/${viewModelClass}.kt" />
+	
+    <instantiate from="root/src/app_package/ViewState.kt.ftl"
+                   to="${escapeXmlAttribute(srcOut)}/${viewStateClass}.kt" />
+    <open file="${escapeXmlAttribute(srcOut)}/${viewStateClass}.kt" />
+	
+    <instantiate from="root/src/app_package/Action.kt.ftl"
+                   to="${escapeXmlAttribute(srcOut)}/${actionClass}.kt" />
+    <open file="${escapeXmlAttribute(srcOut)}/${actionClass}.kt" />
+
+    <#if createViewEvents>
+        <instantiate from="root/src/app_package/ViewEvents.kt.ftl"
+                       to="${escapeXmlAttribute(srcOut)}/${viewEventsClass}.kt" />
+    	<open file="${escapeXmlAttribute(srcOut)}/${viewEventsClass}.kt" />
+    </#if>
+	
+</recipe>
diff --git a/tools/templates/RiotXFeature/root/res/layout/fragment.xml.ftl b/tools/templates/RiotXFeature/root/res/layout/fragment.xml.ftl
new file mode 100644
index 0000000000..539c40f3f9
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/res/layout/fragment.xml.ftl
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout 
+	xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/rootConstraintLayout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="${fragmentClass}"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Action.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/Action.kt.ftl
new file mode 100644
index 0000000000..7492907e6c
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/Action.kt.ftl
@@ -0,0 +1,5 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import im.vector.riotx.core.platform.VectorViewModelAction
+
+sealed class ${actionClass}: VectorViewModelAction
\ No newline at end of file
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Activity.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/Activity.kt.ftl
new file mode 100644
index 0000000000..fdac319482
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/Activity.kt.ftl
@@ -0,0 +1,49 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import android.content.Context
+import android.content.Intent
+import androidx.appcompat.widget.Toolbar
+import im.vector.riotx.R
+import im.vector.riotx.core.extensions.addFragment
+import im.vector.riotx.core.platform.ToolbarConfigurable
+import im.vector.riotx.core.platform.VectorBaseActivity
+
+//TODO: add this activity to manifest
+class ${activityClass} : VectorBaseActivity(), ToolbarConfigurable {
+
+    companion object {
+	
+		<#if createFragmentArgs>
+		private const val EXTRA_FRAGMENT_ARGS = "EXTRA_FRAGMENT_ARGS"
+		
+		fun newIntent(context: Context, args: ${fragmentArgsClass}): Intent {
+		     return Intent(context, ${activityClass}::class.java).apply {
+		         putExtra(EXTRA_FRAGMENT_ARGS, args)
+		      }
+		}
+		<#else>
+        fun newIntent(context: Context): Intent {
+            return Intent(context, ${activityClass}::class.java)
+        }
+		</#if>
+    }
+
+    override fun getLayoutRes() = R.layout.activity_simple
+
+    override fun initUiAndData() {
+        if (isFirstCreation()) {
+			<#if createFragmentArgs>
+			val fragmentArgs: ${fragmentArgsClass} = intent?.extras?.getParcelable(EXTRA_FRAGMENT_ARGS)
+                                                   ?: return
+            addFragment(R.id.simpleFragmentContainer, ${fragmentClass}::class.java, fragmentArgs)
+			<#else>
+			addFragment(R.id.simpleFragmentContainer, ${fragmentClass}::class.java)
+			</#if>
+        }
+    }
+
+    override fun configure(toolbar: Toolbar) {
+        configureToolbar(toolbar)
+    }
+
+}
diff --git a/tools/templates/RiotXFeature/root/src/app_package/Fragment.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/Fragment.kt.ftl
new file mode 100644
index 0000000000..df69078d9d
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/Fragment.kt.ftl
@@ -0,0 +1,47 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import android.os.Bundle
+<#if createFragmentArgs>
+import android.os.Parcelable
+import kotlinx.android.parcel.Parcelize
+import com.airbnb.mvrx.args
+</#if>
+import android.view.View
+import com.airbnb.mvrx.fragmentViewModel
+import com.airbnb.mvrx.withState
+import im.vector.riotx.R
+import im.vector.riotx.core.platform.VectorBaseFragment
+import javax.inject.Inject
+
+<#if createFragmentArgs>
+@Parcelize
+data class ${fragmentArgsClass}() : Parcelable
+</#if>
+
+//TODO: add this fragment into FragmentModule
+class ${fragmentClass} @Inject constructor(
+        private val viewModelFactory: ${viewModelClass}.Factory
+) : VectorBaseFragment(), ${viewModelClass}.Factory by viewModelFactory {
+
+	<#if createFragmentArgs>
+		private val fragmentArgs: ${fragmentArgsClass} by args()
+	</#if>
+    private val viewModel: ${viewModelClass} by fragmentViewModel()
+
+    override fun getLayoutResId() = R.layout.${fragmentLayout}
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+		// Initialize your view, subscribe to viewModel... 
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+		// Clear your view, unsubscribe...
+    }
+
+    override fun invalidate() = withState(viewModel) { state ->
+        //TODO
+    }
+
+}
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewEvents.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/ViewEvents.kt.ftl
new file mode 100644
index 0000000000..4d7d2ee450
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/ViewEvents.kt.ftl
@@ -0,0 +1,5 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import im.vector.riotx.core.platform.VectorViewEvents
+
+sealed class ${viewEventsClass} : VectorViewEvents
\ No newline at end of file
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewModel.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/ViewModel.kt.ftl
new file mode 100644
index 0000000000..f4090b40e6
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/ViewModel.kt.ftl
@@ -0,0 +1,44 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import com.airbnb.mvrx.ActivityViewModelContext
+import com.airbnb.mvrx.FragmentViewModelContext
+import com.airbnb.mvrx.MvRxViewModelFactory
+import com.airbnb.mvrx.ViewModelContext
+import com.squareup.inject.assisted.Assisted
+import com.squareup.inject.assisted.AssistedInject
+import im.vector.riotx.core.platform.VectorViewModel
+
+<#if createViewEvents>
+<#else>
+import im.vector.riotx.core.platform.EmptyViewEvents
+</#if>
+
+class ${viewModelClass} @AssistedInject constructor(@Assisted initialState: ${viewStateClass})
+    <#if createViewEvents>
+    : VectorViewModel<${viewStateClass}, ${actionClass}, ${viewEventsClass}>(initialState) {
+    <#else>
+    : VectorViewModel<${viewStateClass}, ${actionClass}, EmptyViewEvents>(initialState) {
+    </#if>
+
+    @AssistedInject.Factory
+    interface Factory {
+        fun create(initialState: ${viewStateClass}): ${viewModelClass}
+    }
+
+    companion object : MvRxViewModelFactory<${viewModelClass}, ${viewStateClass}> {
+
+        @JvmStatic
+        override fun create(viewModelContext: ViewModelContext, state: ${viewStateClass}): ${viewModelClass}? {
+            val factory = when (viewModelContext) {
+                is FragmentViewModelContext -> viewModelContext.fragment as? Factory
+                is ActivityViewModelContext -> viewModelContext.activity as? Factory
+            }
+            return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
+        }
+    }
+
+    override fun handle(action: ${actionClass}) {
+		//TODO
+    }
+
+}
diff --git a/tools/templates/RiotXFeature/root/src/app_package/ViewState.kt.ftl b/tools/templates/RiotXFeature/root/src/app_package/ViewState.kt.ftl
new file mode 100644
index 0000000000..55e1f5f549
--- /dev/null
+++ b/tools/templates/RiotXFeature/root/src/app_package/ViewState.kt.ftl
@@ -0,0 +1,5 @@
+package ${escapeKotlinIdentifiers(packageName)}
+
+import com.airbnb.mvrx.MvRxState
+
+data class ${viewStateClass}() : MvRxState
\ No newline at end of file
diff --git a/tools/templates/RiotXFeature/template.xml b/tools/templates/RiotXFeature/template.xml
new file mode 100644
index 0000000000..33d2edfc70
--- /dev/null
+++ b/tools/templates/RiotXFeature/template.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<template
+    format="5"
+    revision="1"
+    name="RiotX Feature"
+    minApi="19"
+    minBuildApi="19"
+    description="Creates a new activity and a fragment with view model, view state and actions">
+
+    <category value="New Vector" />
+    <formfactor value="Mobile" />
+	
+  	 <parameter
+  	    id="createActivity"
+  	    name="Create host activity"
+  	    type="boolean"
+  	    default="true"
+  	    help="If true, you will have a host activity" />
+
+    <parameter
+        id="activityClass"
+        name="Activity Name"
+        type="string"
+        constraints="class|unique|nonempty"
+		visibility="createActivity"
+        default="MainActivity"
+        help="The name of the activity class to create" />
+
+    <parameter
+        id="fragmentClass"
+        name="Fragment Name"
+        type="string"
+        constraints="class|unique|nonempty"
+        suggest="${underscoreToCamelCase(classToResource(activityClass))}Fragment"
+        default="MainFragment"
+        help="The name of the fragment class to create" />
+		
+   	 <parameter
+   	    id="createFragmentArgs"
+   	    name="Create fragment Args"
+   	    type="boolean"
+   	    default="false"
+   	    help="If true, you will have a fragment args" />
+		
+	 <parameter
+	    id="fragmentArgsClass"
+	    name="Fragment Args"
+	    type="string"
+	    constraints="class|unique|nonempty"
+		visibility="createFragmentArgs"
+        suggest="${underscoreToCamelCase(classToResource(fragmentClass))}Args"
+	    default="MainArgs"
+	    help="The name of the fragment args to create" />
+		
+    <parameter
+        id="fragmentLayout"
+        name="Fragment Layout Name"
+        type="string"
+        constraints="layout|unique|nonempty"
+        suggest="fragment_${classToResource(fragmentClass)}"
+        default="main_fragment"
+        help="The name of the layout to create for the fragment" />
+
+    <parameter
+        id="viewModelClass"
+        name="ViewModel Name"
+        type="string"
+        constraints="class|unique|nonempty"
+        suggest="${underscoreToCamelCase(classToResource(fragmentClass))}ViewModel"
+        default="MainViewModel"
+        help="The name of the view model class to create" />
+		
+	 <parameter
+	    id="actionClass"
+	    name="Action Name"
+	    type="string"
+	    constraints="class|unique|nonempty"
+	    suggest="${underscoreToCamelCase(classToResource(fragmentClass))}Action"
+	    default="MainAction"
+	    help="The name of the action class to create" />
+			
+	  <parameter
+		 id="viewStateClass"
+		 name="ViewState Name"
+		 type="string"
+		 constraints="class|unique|nonempty"
+		 suggest="${underscoreToCamelCase(classToResource(fragmentClass))}ViewState"
+		 default="MainViewState"
+		 help="The name of the ViewState class to create" />
+
+	 <parameter
+   	    id="createViewEvents"
+   	    name="Create ViewEvents"
+   	    type="boolean"
+   	    default="false"
+   	    help="If true, you will have a view events" />
+		
+	 <parameter
+	    id="viewEventsClass"
+	    name="ViewEvents Class"
+	    type="string"
+	    constraints="class|unique|nonempty"
+	    visibility="createViewEvents"
+
+        suggest="${underscoreToCamelCase(classToResource(fragmentClass))}ViewEvents"
+	    default="MainViewEvents"
+	    help="The name of the view events to create" />
+
+
+		
+    <parameter
+        id="packageName"
+        name="Package name"
+        type="string"
+        constraints="package"
+        default="com.mycompany.myapp" />
+
+    <globals file="globals.xml.ftl" />
+    <execute file="recipe.xml.ftl" />
+
+</template>
diff --git a/tools/templates/configure.sh b/tools/templates/configure.sh
new file mode 100755
index 0000000000..eb2aa0dbec
--- /dev/null
+++ b/tools/templates/configure.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+#
+# Copyright 2020 New Vector Ltd
+#
+# Licensed 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.
+#
+
+echo "Configure RiotX Template..."
+{
+ln -s $(pwd)/RiotXFeature /Applications/Android\ Studio.app/Contents/plugins/android/lib/templates/other
+} && {
+  echo "Please restart Android Studio."
+}
diff --git a/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt
index bda4426c45..e82e8b3856 100644
--- a/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt
+++ b/vector/src/main/java/im/vector/riotx/core/platform/VectorViewModel.kt
@@ -30,6 +30,10 @@ import io.reactivex.Single
 abstract class VectorViewModel<S : MvRxState, VA : VectorViewModelAction, VE : VectorViewEvents>(initialState: S)
     : BaseMvRxViewModel<S>(initialState, false) {
 
+    interface Factory<S: MvRxState> {
+        fun create(state: S): BaseMvRxViewModel<S>
+    }
+
     // Used to post transient events to the View
     protected val _viewEvents = PublishDataSource<VE>()
     val viewEvents: DataSource<VE> = _viewEvents