diff --git a/public/config/config.json b/public/config/config.json
index 537e865a61060fc9fb1cb617d31a0b89c50d93db..4593a147766d307f0891937622a7b0ee3b46dee3 100644
--- a/public/config/config.json
+++ b/public/config/config.json
@@ -7,7 +7,7 @@
     "VUE_APP_APPLICATION_FAVICO":"/geocontrib/img/geo2f.ico",
     "VUE_APP_APPLICATION_ABSTRACT":"Application de saisie d'informations géographiques contributive",
     "VUE_APP_LOGO_PATH":"/geocontrib/img/logo-neogeo-circle.png",
-    "VUE_APP_DJANGO_BASE":"http://localhost:8010",
+    "VUE_APP_DJANGO_BASE":"http://localhost:8010/",
     "VUE_APP_DJANGO_API_BASE":"http://localhost:8010/api/",
     "VUE_APP_RELOAD_INTERVAL": 15000,
     "VUE_APP_DISABLE_LOGIN_BUTTON":false,
diff --git a/src/App.vue b/src/App.vue
index 964cfd77ac5e2480361fb249dc59952ae2d3d255..6213eb57f3c95d6abfa19fa522fd36c8f87a9e69 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -118,6 +118,11 @@
               </div>
             </div>
           </div>
+          <div class="desktop flex push-right-desktop item title">
+            <span>
+              {{ APPLICATION_ABSTRACT }}
+            </span>
+          </div>
 
           <div class="desktop flex push-right-desktop">
             <router-link v-if="user" :to="{name: 'my_account'}" class="item">
@@ -218,17 +223,24 @@ export default {
 
   computed: {
     ...mapState([
-      "projects",
       "user",
       "USER_LEVEL_PROJECTS",
       "configuration",
       "messages",
       "loader",
     ]),
-    ...mapGetters(["project"]),
+    ...mapState('projects', [
+      'projects'
+    ]),
+    ...mapGetters( 'projects', [
+      'project'
+    ]),
     APPLICATION_NAME() {
       return this.configuration.VUE_APP_APPLICATION_NAME;
     },
+    APPLICATION_ABSTRACT() {
+      return this.$store.state.configuration.VUE_APP_APPLICATION_ABSTRACT;
+    },
     DISABLE_LOGIN_BUTTON() {
       return this.configuration.VUE_APP_DISABLE_LOGIN_BUTTON;
     },
@@ -384,6 +396,28 @@ footer {
   transition: none !important;
 }
 
+.item.title::before {
+  background: none !important;
+}
+
+
+.bounce-enter-active {
+  animation: bounce-in .5s;
+}
+.bounce-leave-active {
+  animation: bounce-in .5s reverse;
+}
+@keyframes bounce-in {
+  0% {
+    transform: scale(0);
+  }
+  50% {
+    transform: scale(1.5);
+  }
+  100% {
+    transform: scale(1);
+  }
+}
 .ui.grid > .row.over-content {
   position: absolute;
   z-index: 99;
diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css
index 6f7a4e7c4823bf725373cdbbab5450879bdf84ed..54967e93dfa00977620d28a5f91802b0bee582ec 100644
--- a/src/assets/styles/base.css
+++ b/src/assets/styles/base.css
@@ -168,7 +168,57 @@ footer .ui.text.menu .item:not(:first-child) {
 }
 
 /* ---------------------------------- */
-      /* ERROR LIST */
+      /* PAGINATION */
+/* ---------------------------------- */
+
+.custom-pagination {
+  display: flex;
+  align-items: center;
+  list-style: none;
+  font-size: 1.3em;
+}
+
+.custom-pagination > .page-item > .page-link {
+  border: none;
+  font-weight: 400;
+  color: #008080;
+}
+.custom-pagination  > .page-item.active > .page-link {
+  color: #008080;
+  background-color: transparent;
+  font-weight: bolder;
+  text-shadow: 0 0 2px #008080;
+  padding: 0.325em 0.75em;
+  pointer-events: none;
+}
+.custom-pagination > .page-item.disabled > .page-link {
+  opacity: 0.5;
+  pointer-events: none;
+}
+
+.custom-pagination > div > .page-item > .page-link {
+  border: none;
+  font-weight: 400;
+  color: #008080;
+  padding: 0.325em 0.75em;
+}
+.custom-pagination > div > .page-item.active > .page-link {
+  color: #008080;
+  background-color: transparent;
+  font-weight: bolder;
+  font-size: 1.2em;
+  text-shadow: 0 0 2px #008080;
+  padding: 0.325em 0.75em;
+  pointer-events: none;
+}
+.custom-pagination > div > .page-item.disabled > .page-link {
+  opacity: 0.5;
+  padding: 0.325em 0.75em;
+  pointer-events: none;
+}
+
+/* ---------------------------------- */
+      /* MULTISELECT */
 /* ---------------------------------- */
 .multiselect__tags {
   border: 2px solid #ced4da;
@@ -209,4 +259,15 @@ footer .ui.text.menu .item:not(:first-child) {
   background-color: #fff;
   opacity: 1;
   top: 2px;
+}
+
+#search-projects > .multiselect > .multiselect__tags {
+  border-radius: 0 !important;
+}
+
+.menu.projects > .item > .multiselect {
+  min-height: 0px !important;
+}
+.menu.projects > .item > .multiselect > .multiselect__tags {
+  min-height: 0px !important;
 }
\ No newline at end of file
diff --git a/src/components/Pagination.vue b/src/components/Pagination.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dfee522be8eeed3dd10e7e80bd988f12bf79ca0f
--- /dev/null
+++ b/src/components/Pagination.vue
@@ -0,0 +1,137 @@
+<template>
+  <div style="display: flex;">
+    <nav style="margin: 0 auto;">
+      <ul class="custom-pagination">
+        <li
+          class="page-item"
+          :class="{ disabled: page === 1 }"
+        >
+          <a
+            class="page-link"
+            href="#"
+            @click="page -= 1"
+          >
+            <i class="ui icon big angle left" />
+          </a>
+        </li>
+        <div v-if="nbPages > 5" style="display: contents;">
+          <li
+            v-for="index in pagination(page, nbPages)"
+            :key="index"
+            class="page-item"
+            :class="{ active: page === index }"
+          >
+            <a
+              class="page-link"
+              href="#"
+              @click="changePage(index)"
+            >
+              {{ index }}
+            </a>
+          </li>
+        </div>
+        <div v-else style="display: contents;">
+          <li
+            v-for="index in nbPages"
+            :key="index"
+            class="page-item"
+            :class="{ active: page === index }"
+          >
+            <a
+              class="page-link"
+              href="#"
+              @click="page = index"
+            >
+              {{ index }}
+            </a>
+          </li>
+        </div>
+        <li
+          class="page-item"
+          :class="{ disabled: page === nbPages }"
+        >
+          <a
+            class="page-link"
+            href="#"
+            @click="page += 1"
+          >
+            <i class="ui icon big angle right" />
+          </a>
+        </li>
+      </ul>
+    </nav>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Pagination',
+
+  props: {
+    nbPages: {
+      type: Number,
+      default: 1
+    },
+
+    onPageChange: {
+      type: Function,
+      default: () => {
+        return () => 1;
+      }
+    }
+  },
+
+  data() {
+    return {
+      page: 1
+    }
+  },
+
+  watch: {
+    page: function(newValue, oldValue) {
+      if (newValue !== oldValue) {
+        this.onPageChange(newValue);
+        this.$emit('change-page', newValue);
+      }
+    }
+  },
+
+  methods: {
+    pagination(c, m) {
+      const current = c,
+            last = m,
+            delta = 2,
+            left = current - delta,
+            right = current + delta + 1,
+            range = [],
+            rangeWithDots = [];
+      let   l;
+
+      for (let i = 1; i <= last; i++) {
+        if (i === 1 || i === last || i >= left && i < right) {
+            range.push(i);
+        }
+      }
+      for (const i of range) {
+        if (l) {
+          if (i - l === 2) {
+              rangeWithDots.push(l + 1);
+          } else if (i - l !== 1) {
+              rangeWithDots.push('...');
+          }
+        }
+        rangeWithDots.push(i);
+        l = i;
+      }
+
+      return rangeWithDots;
+    },
+
+    changePage(num) {
+      if (typeof num === 'number') {
+        this.page = num;
+      }
+    }
+  }
+}
+</script>
diff --git a/src/components/Projects/DropdownMenuItem.vue b/src/components/Projects/DropdownMenuItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ae0ebdb63ad019c1cee232e43df0c10b6de8c580
--- /dev/null
+++ b/src/components/Projects/DropdownMenuItem.vue
@@ -0,0 +1,89 @@
+<template>
+  <Multiselect
+		v-model="selection"
+		:options="options"
+		:allow-empty="true"
+		track-by="label"
+		label="label"
+		:reset-after="false"
+		select-label=""
+		selected-label=""
+		deselect-label=""
+		:searchable="false"
+		:placeholder="placeholder"
+		:clear-on-select="false"
+		:preserve-search="true"
+		@select="select"
+		@close="close"
+	>
+		<!-- <template slot="clear">
+			<div
+				v-if="selection"
+				class="multiselect__clear"
+				@click.prevent.stop="selection = options[0]"
+			>
+				<i class="close icon"></i>
+			</div>
+		</template> -->
+	</Multiselect>
+</template>
+
+<script>
+import Multiselect from 'vue-multiselect';
+
+export default {
+  name: 'DropdownMenuItem',
+
+	components: {
+		Multiselect
+	},
+
+	props: {
+		placeholder: {
+			type: String,
+			default: 'Sélectionnez une valeur'
+		},
+		options: {
+			type: Array,
+			default: () => {
+				return [];
+			}
+		}
+	},
+
+  data() {
+    return {
+      selection: null,
+    }
+  },
+
+	watch: {
+		selection: {
+			deep: true,
+			handler(newValue) {
+				if (!newValue) {
+					this.selection = this.options[0];
+					this.$emit('filter', this.selection);
+				}
+			}
+		}
+	},
+
+	created() {
+		this.selection = this.options[0];
+	},
+
+  methods: {
+    select(e) {
+      this.$emit('filter', e);
+    },
+    close() {
+      this.$emit('close', this.selection);
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+
+</style>
diff --git a/src/components/Projects/ProjectsMenu.vue b/src/components/Projects/ProjectsMenu.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8eea8a9a7fb4354dd571bbea1ac0a9ce636c3b42
--- /dev/null
+++ b/src/components/Projects/ProjectsMenu.vue
@@ -0,0 +1,155 @@
+<template>
+	<div class="ui menu projects">
+		<div class="item">
+			<label>
+				Modération
+			</label>
+			<DropdownMenuItem
+				:options="moderationOptions"
+				v-on="$listeners"
+			/>
+		</div>
+		<div class="item">
+			<label>
+				Niveau d'autorisation requis
+			</label>
+			<DropdownMenuItem
+				:options="accessLevelOptions"
+				v-on="$listeners"
+			/>
+		</div>
+		<div class="item">
+			<label>
+				Mon niveau d'autorisation
+			</label>
+			<DropdownMenuItem
+				:options="userAccessLevelOptions"
+				v-on="$listeners"
+			/>
+		</div>
+		<div class="right item">
+			<search-projects
+				:search-function="SEARCH_PROJECTS"
+			/>
+		</div>
+	</div>
+</template>
+
+<script>
+import { mapActions } from 'vuex';
+
+import DropdownMenuItem from '@/components/Projects/DropdownMenuItem.vue';
+import SearchProjects from '@/components/Projects/SearchProjects.vue';
+
+export default {
+	name: 'ProjectsMenu',
+
+	components: {
+		DropdownMenuItem,
+		SearchProjects,
+	},
+
+	data() {
+		return {
+			moderationOptions: [
+				{
+					label: 'Tous',
+					filter: 'moderation',
+					value: null
+				},
+				{
+					label: 'Projet modéré',
+					filter: 'moderation',
+					value: 'true'
+				},
+				{
+					label: 'Projet non modéré',
+					filter: 'moderation',
+					value: 'false'
+				},
+			],
+			accessLevelOptions: [
+				{
+					label: 'Tous',
+					filter: 'access_level',
+					value: null
+				},
+				{
+					label: 'Utilisateur connecté',
+					filter: 'access_level',
+					value: 'logged_user'
+				},
+				{
+					label: 'Contributeur',
+					filter: 'access_level',
+					value: 'contributor'
+				},
+				{
+					label: 'Modérateur',
+					filter: 'access_level',
+					value: 'moderator'
+				},
+				{
+					label: 'Administrateur projet',
+					filter: 'access_level',
+					value: 'admin'
+				},
+			],
+			userAccessLevelOptions: [
+				{
+					label: 'Tous',
+					filter: 'user_access_level',
+					value: null
+				},
+				{
+					label: 'Utilisateur connecté',
+					filter: 'user_access_level',
+					value: '1'
+				},
+				{
+					label: 'Contributeur',
+					filter: 'user_access_level',
+					value: '2'
+				},
+				{
+					label: 'Modérateur',
+					filter: 'user_access_level',
+					value: '3'
+				},
+				{
+					label: 'Administrateur projet',
+					filter: 'user_access_level',
+					value: '4'
+				},
+			]
+		}
+	},
+
+	methods: {
+		...mapActions('projects', [
+			'SEARCH_PROJECTS'
+		])
+	}
+}
+</script>
+
+<style lang="less" scoped>
+.projects {
+	.item {
+		display: flex;
+		flex-direction: column;
+		align-items: flex-start !important;
+
+		padding: 0.4em 0.6em;
+
+		label {
+			margin-bottom: 0.2em;
+			font-size: 0.9em;
+			font-weight: 600;
+		}
+	}
+	.item {
+		width: 25%;
+	}
+}
+</style>
diff --git a/src/components/Projects/SearchProjects.vue b/src/components/Projects/SearchProjects.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3fa8e94b4188ed80475c7d7c97628a87784d5b49
--- /dev/null
+++ b/src/components/Projects/SearchProjects.vue
@@ -0,0 +1,67 @@
+<template>
+	<div id="search-projects">
+    <input
+      v-model="text"
+      type="search"
+      placeholder="Rechercher..."
+    >
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+import { mapMutations } from 'vuex';
+
+export default {
+  name: 'SearchProjects',
+
+  props: {
+    searchFunction: {
+      type: Function,
+      default: () => { return {} }
+    }
+	},
+
+  data() {
+    return {
+      text: null
+    }
+  },
+
+  watch: {
+    text: _.debounce(function(newValue) {
+      this.$emit('loading', true);
+      this.SET_CURRENT_PAGE(1);
+      this.searchFunction(newValue)
+        .then(() => {
+          this.$emit('loading', false);
+        });
+    }, 100)
+  },
+
+  methods: {
+    ...mapMutations('projects', [
+      'SET_CURRENT_PAGE'
+    ])
+  }
+}
+</script>
+
+<style lang="less" scoped>
+#search-projects {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-end;
+  input {
+    width: 100%;
+    height: 72%;
+    text-align: left;
+    color: #35495e;
+    padding: 8px 40px 0 8px;
+    border-radius: 5px;
+    border: 1px solid #e8e8e8;
+    font-size: 14px;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 3ff59325ded1f4dff75020ca8abb256e0edcdd0b..864c9a69f193ed2fb775913c379530f3fa719fe7 100644
--- a/src/main.js
+++ b/src/main.js
@@ -3,8 +3,8 @@ import Vue from 'vue'
 
 import App from './App.vue'
 import './registerServiceWorker'
-import router from './router'
-import store from './store'
+import router from '@/router'
+import store from '@/store'
 import 'leaflet/dist/leaflet.css';
 import 'leaflet-draw/dist/leaflet.draw.css';
 import '@/assets/resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.css';
@@ -48,8 +48,9 @@ let onConfigLoaded = function(config){
   document.head.appendChild(link);
 
   window.proxy_url=config.VUE_APP_DJANGO_API_BASE+"proxy/";
-  axios.all([store.dispatch("USER_INFO"),
-    store.dispatch("GET_ALL_PROJECTS"),
+  axios.all([
+    store.dispatch("USER_INFO"),
+    store.dispatch('projects/GET_ALL_PROJECTS'),
     store.dispatch("GET_STATIC_PAGES"),
     store.dispatch("GET_USER_LEVEL_PROJECTS"),
     store.dispatch("map/GET_AVAILABLE_LAYERS"),
diff --git a/src/router/index.js b/src/router/index.js
index f335b9e01be58a26d80966e245a9a7895ee048c7..9aaed61eb1a304565beac70c149c901afb72e30c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,6 +1,6 @@
 import Vue from 'vue'
 import VueRouter from 'vue-router'
-import Index from '../views/Index.vue'
+import Projects from '../views/Projects.vue'
 
 Vue.use(VueRouter)
 
@@ -13,7 +13,7 @@ const routes = [
   {
     path: '/',
     name: 'index',
-    component: Index
+    component: Projects
   },
   {
     path: '/connexion/',
diff --git a/src/services/project-api.js b/src/services/project-api.js
index 6c9e7a83746313983b4feb658012b2ea4a985d3f..93c19e017d8ceb9bc5fcd7a4537dfa9274e36419 100644
--- a/src/services/project-api.js
+++ b/src/services/project-api.js
@@ -1,13 +1,9 @@
 import axios from '@/axios-client.js';
-import store from '../store'
 
 
-
-
-const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
-
 const projectAPI = {
-  async getProjectSubscription({ projectSlug }) {
+
+  async getProjectSubscription({ baseUrl, projectSlug }) {
     const response = await axios.get(
       `${baseUrl}projects/${projectSlug}/subscription/`
     );
@@ -21,7 +17,7 @@ const projectAPI = {
     }
   },
 
-  async subscribeProject({ projectSlug, suscribe }) {
+  async subscribeProject({ baseUrl, projectSlug, suscribe }) {
     const response = await axios.put(
       `${baseUrl}projects/${projectSlug}/subscription/`,
       { is_suscriber: suscribe }
@@ -36,6 +32,30 @@ const projectAPI = {
     }
   },
 
+  async getProjects(baseUrl, filters, page) {
+    try {
+      const url = `${baseUrl}projects/?page=${page}`;
+
+      let filteredUrl;
+      if (Object.values(filters).some(el => el && el.length > 0)) {
+        filteredUrl = url;
+        for (const filter in filters) {
+          if (filters[filter]) {
+            filteredUrl = filteredUrl.concat('', `&${filter}=${filters[filter]}`);
+          }
+        }
+      }
+
+      const response = await axios.get(filteredUrl ? filteredUrl : url);
+      if (response.status === 200 && response.data) {
+        return response.data;
+      }
+    } catch (error) {
+      console.error(error);
+      throw error;
+    }
+  },
+
   async deleteProject(projectSlug) {
     const response = await axios.delete(
       `${baseUrl}projects/${projectSlug}`
diff --git a/src/store/index.js b/src/store/index.js
index a6c2008102fb6e5ace554cbc6339f6303893e276..661b004bc6774f414a06c74c719c65255f7985f5 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -2,9 +2,7 @@ import axios from '@/axios-client.js';
 import Vue from 'vue';
 import Vuex from 'vuex';
 import router from '../router'
-import feature_type from "./modules/feature_type"
-import feature from "./modules/feature"
-import map from "./modules/map"
+import modules from './modules';
 
 Vue.use(Vuex);
 
@@ -24,17 +22,12 @@ const noPermissions = {
 };
 
 export default new Vuex.Store({
-  modules: {
-    feature_type,
-    feature,
-    map
-  },
+  modules,
+  
   state: {
     logged: false,
     user: false,
     configuration: null,
-    project_slug: null,
-    projects: [],
     last_comments: [],
     staticPages: null,
     USER_LEVEL_PROJECTS: null,
@@ -51,15 +44,6 @@ export default new Vuex.Store({
   },
 
   mutations: {
-    SET_PROJECTS(state, projects) {
-      state.projects = projects;
-    },
-    ADD_PROJECT(state, project) {
-      state.projects = [project, ...state.projects];
-    },
-    SET_PROJECT_SLUG(state, slug) {
-      state.project_slug = slug;
-    },
     SET_USER(state, payload) {
       state.user = payload;
     },
@@ -133,31 +117,10 @@ export default new Vuex.Store({
   },
 
   getters: {
-    project: state => state.projects.find((project) => project.slug === state.project_slug),
-    permissions: state => state.user_permissions ? state.user_permissions[state.project_slug] : noPermissions,
-    // TODO: utiliser et créer point api depuis ProjectTypeListView lors du passage à la pagination des projets
-    project_types: state => state.projects.filter(projet => projet.is_project_type),
-    project_user: state => state.projects.filter(projet => projet.creator === state.user.id),
+    permissions: state => state.user_permissions ? state.user_permissions[state.projects.project_slug] : noPermissions,
   },
 
   actions: {
-    GET_ALL_PROJECTS({ commit }) {
-      function parseDate(date) {
-        let dateArr = date.split("/").reverse();
-        return new Date(dateArr[0], dateArr[1] - 1, dateArr[2]);
-      }
-      return axios
-        .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}projects/`)
-        .then((response) => {
-          if (response.status === 200 && response.data) {
-            const orderedProjects = response.data.sort((a, b) => parseDate(b.created_on) - parseDate(a.created_on));
-            commit("SET_PROJECTS", orderedProjects);
-          }
-        })
-        .catch((error) => {
-          throw error;
-        });
-    },
     GET_STATIC_PAGES({ commit }) {
       return axios
         .get(`${this.state.configuration.VUE_APP_DJANGO_API_BASE}flat-pages/`)
@@ -301,7 +264,7 @@ export default new Vuex.Store({
     },
 
     async GET_PROJECT_INFO({ state, commit, dispatch }, slug) {
-      commit("SET_PROJECT_SLUG", slug);
+      commit('projects/SET_PROJECT_SLUG', slug, { root: true });
       let promises = [
         dispatch("GET_PROJECT_LAST_MESSAGES", slug).then(response => response),
         dispatch("feature_type/GET_PROJECT_FEATURE_TYPES", slug).then(response => response),
diff --git a/src/store/modules/feature.js b/src/store/modules/feature.store.js
similarity index 99%
rename from src/store/modules/feature.js
rename to src/store/modules/feature.store.js
index 436e57097da5f67c7cb72d13e3aa6f1436305790..0ae63837993517da7a8e93e8a3ff574983956226 100644
--- a/src/store/modules/feature.js
+++ b/src/store/modules/feature.store.js
@@ -190,7 +190,7 @@ const feature = {
                 message: routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée"
               },
             });
-            dispatch("GET_ALL_PROJECTS", null, {root:true}) //* & refresh project list
+            dispatch('projects/GET_ALL_PROJECTS', null, { root:true }) //* & refresh project list
           });
       }
 
diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.store.js
similarity index 100%
rename from src/store/modules/feature_type.js
rename to src/store/modules/feature_type.store.js
diff --git a/src/store/modules/index.js b/src/store/modules/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d6e07fc7dbab29baf8d622222c06f2b98896fe1c
--- /dev/null
+++ b/src/store/modules/index.js
@@ -0,0 +1,15 @@
+/**
+ * Automatically imports all the modules and exports as a single module object
+**/
+const requireModule = require.context('.', false,  /\.store\.js$/);
+const modules = {};
+
+requireModule.keys().forEach(filename => {
+  // create the module name from fileName
+  // remove the store.js extension
+  const moduleName = filename.replace(/(\.\/|\.store\.js)/g, '');
+
+  modules[moduleName] = requireModule(filename).default || requireModule(filename);
+});
+
+export default modules;
\ No newline at end of file
diff --git a/src/store/modules/map.js b/src/store/modules/map.store.js
similarity index 100%
rename from src/store/modules/map.js
rename to src/store/modules/map.store.js
diff --git a/src/store/modules/projects.store.js b/src/store/modules/projects.store.js
new file mode 100644
index 0000000000000000000000000000000000000000..194a9973632709f974d637f6aa31a965ee6291a8
--- /dev/null
+++ b/src/store/modules/projects.store.js
@@ -0,0 +1,139 @@
+import axios from '@/axios-client.js';
+import projectAPI from '@/services/project-api';
+
+const projects = {
+
+  namespaced: true,
+
+  state: {
+    currentPage: 1,
+    projects: [],
+    count: 0,
+    project_slug: null,
+    filters: {
+      moderation: null,
+      access_level: null,
+      user_access_level: null
+    },
+    searchProjectsFilter: null,
+    isProjectsListSearched: null,
+  },
+
+  getters: {
+    project: state => state.projects.find((project) => project.slug === state.project_slug),
+    project_types: state => state.projects.filter(projet => projet.is_project_type),
+    project_user: state => state.projects.filter(projet => projet.creator === state.user.id),
+  },
+
+  mutations: {
+    SET_CURRENT_PAGE (state, payload) {
+      state.currentPage = payload;
+    },
+
+    SET_PROJECTS(state, projects) {
+      state.projects = projects.results;
+      state.count = projects.count;
+    },
+
+    ADD_PROJECT(state, project) {
+      state.projects = [project, ...state.projects];
+    },
+
+    SET_PROJECT_SLUG(state, slug) {
+      state.project_slug = slug;
+    },
+
+    SET_PROJECTS_FILTER(state, payload) {
+      state.filters[payload.filter] = payload.value;
+    },
+
+    SET_PROJECTS_SEARCH_STATE(state, payload) {
+      state.isProjectsListSearched = payload.isSearched;
+      state.searchProjectsFilter = payload.text;
+    },
+  },
+
+  actions: {
+    async GET_ALL_PROJECTS({ rootState, commit }) {
+      try {
+        const response = await axios
+          .get(`${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/`);
+        if (response.status === 200 && response.data) {
+          // const orderedProjects = response.data.sort((a, b) => parseDate(b.created_on) - parseDate(a.created_on));
+          commit('SET_PROJECTS', response.data);
+        }
+      } catch (error) {
+        console.error(error);
+        throw error;
+      }
+    },
+
+    async GET_PROJECTS({ state, rootState, commit }, page) {
+      if (!page) {
+        page = state.currentPage;
+      }
+      const baseUrl = rootState.configuration.VUE_APP_DJANGO_API_BASE;
+      const projects = await projectAPI.getProjects(baseUrl, state.filters, page);
+      commit('SET_PROJECTS', projects);
+    },
+
+    async SEARCH_PROJECTS({ commit, dispatch }, text) {
+      if (text) {
+        await dispatch('HANDLE_PROJECTS_SEARCH_REQUEST', text);
+      } else {
+        commit('SET_PROJECTS_SEARCH_STATE', {
+          isSearched: false,
+          text: null
+        });
+        await dispatch('GET_PROJECTS');
+      }
+    },
+
+    async HANDLE_PROJECTS_SEARCH_REQUEST({ state, rootState, commit }, text) {
+
+      if (rootState.cancellableSearchRequest.length > 0) {
+        const currentRequestCancelToken =
+          rootState.cancellableSearchRequest[rootState.cancellableSearchRequest.length - 1];
+        currentRequestCancelToken.cancel();
+      }
+  
+      const cancelToken = axios.CancelToken.source();
+      commit('SET_CANCELLABLE_SEARCH_REQUEST', cancelToken, { root: true });
+  
+      const url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}projects/?search=${text}`;
+      let filteredUrl;
+      if (Object.values(state.filters).some(el => el && el.length > 0)) {
+        filteredUrl = url;
+        for (const filter in state.filters) {
+          if (state.filters[filter]) {
+            filteredUrl = filteredUrl.concat('', `&${filter}=${state.filters[filter]}`);
+          }
+        }
+      }
+  
+      try {
+        const response = await axios.get(
+          filteredUrl ? filteredUrl : url,
+          {
+            cancelToken: cancelToken.token,
+          }
+        );
+        if (response.status === 200) {
+          const projects = response.data;
+          if (projects) {
+            commit('SET_PROJECTS', projects);
+            commit('SET_PROJECTS_SEARCH_STATE', {
+              isSearched: true,
+              text: text
+            });
+          }
+        }
+      } catch(err) {
+        console.error(err);
+      }
+    },
+  }
+
+};
+
+export default projects;
diff --git a/src/utils/index.js b/src/utils/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f4e38a208239a1dea567de3f9059854fcbd7048e
--- /dev/null
+++ b/src/utils/index.js
@@ -0,0 +1,4 @@
+export function parseDate(date) {
+  let dateArr = date.split("/").reverse();
+  return new Date(dateArr[0], dateArr[1] - 1, dateArr[2]);
+}
\ No newline at end of file
diff --git a/src/views/My_account.vue b/src/views/My_account.vue
index 162eedc20f53ad512982c19a8ff700730f82791a..857eaf99b04122f5f4083e0d32d661b59e634c9d 100644
--- a/src/views/My_account.vue
+++ b/src/views/My_account.vue
@@ -291,10 +291,12 @@ export default {
     // todo : filter projects to user
     ...mapState([
       "user",
-      "projects",
       "USER_LEVEL_PROJECTS",
       "user_permissions",
     ]),
+    ...mapState('projects', [
+      'projects'
+    ]),
     DJANGO_BASE_URL: function () {
       return this.$store.state.configuration.VUE_APP_DJANGO_BASE;
     },
diff --git a/src/views/Index.vue b/src/views/Projects.vue
similarity index 73%
rename from src/views/Index.vue
rename to src/views/Projects.vue
index 96f4a9b021ac0c93a4ba879913061afbbf09986c..c55e238de208a6b2542d04a5bff17f8476261506 100644
--- a/src/views/Index.vue
+++ b/src/views/Projects.vue
@@ -1,15 +1,10 @@
 <template>
   <div class="fourteen wide column">
-    <img class="ui centered small image" :src="logo" />
-    <!-- :src="LOGO_PATH" -->
-    <h2 class="ui center aligned icon header">
-      <div class="content">
-        {{ APPLICATION_NAME }}
-        <div class="sub header">{{ APPLICATION_ABSTRACT }}</div>
-      </div>
+
+    <h2 class="ui horizontal divider header">
+      PROJETS
     </h2>
 
-    <h4 id="les_projets" class="ui horizontal divider header">PROJETS</h4>
     <div class="flex">
       <router-link
         v-if="user && user.can_create_project && isOffline() != true"
@@ -29,6 +24,12 @@
       </router-link>
     </div>
 
+    <!-- FILTRES DES PROJETS -->
+    <projects-menu
+      @filter="setProjectsFilters"
+    />
+
+    <!-- LISTE DES PROJETS -->
     <div v-if="projects" class="ui divided items">
       <div v-for="project in projects" class="item" :key="project.slug">
         <div class="ui tiny image">
@@ -99,17 +100,41 @@
 
       <div class="item"></div>
     </div>
+
+    <!-- PAGINATION -->
+    <pagination
+      :nbPages="Math.ceil(count/10)"
+      :on-page-change="SET_CURRENT_PAGE"
+      @change-page="changePage"
+    />
+
   </div>
 </template>
 
 <script>
-import { mapState } from "vuex";
+import { mapState, mapMutations, mapActions } from 'vuex';
+
+import ProjectsMenu from '@/components/Projects/ProjectsMenu.vue';
+import Pagination from '@/components/Pagination.vue';
 
 export default {
-  name: "Index",
+  name: 'Projects',
+
+  components: {
+    ProjectsMenu,
+    Pagination
+  },
 
   computed: {
-    ...mapState(["projects", "user", "USER_LEVEL_PROJECTS"]),
+    ...mapState([
+      'user',
+      'USER_LEVEL_PROJECTS'
+    ]),
+    ...mapState('projects', [
+      'projects',
+      'count',
+      'filters'
+    ]),
     APPLICATION_NAME() {
       return this.$store.state.configuration.VUE_APP_APPLICATION_NAME;
     },
@@ -124,7 +149,26 @@ export default {
     },
   },
 
+  watch: {
+    filters: {
+      deep: true,
+      handler(newValue) {
+        if (newValue) {
+          this.getData();
+        }
+      }
+    }
+  },
+
   methods: {
+    ...mapMutations('projects', [
+      'SET_CURRENT_PAGE',
+      'SET_PROJECTS_FILTER'
+    ]),
+    ...mapActions('projects', [
+      'GET_PROJECTS'
+    ]),
+
     isOffline() {
       return navigator.onLine == false;
     },
@@ -132,6 +176,25 @@ export default {
       //* change path of thumbnail to update image
       return "?ver=" + Math.random();
     },
+
+    getData(page) {
+      this.loading = true;
+      this.GET_PROJECTS(page)
+        .then(() => {
+          this.loading = false;
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    changePage(e) {
+      this.getData(e);
+    },
+
+    setProjectsFilters(e) {
+      this.SET_PROJECTS_FILTER(e);
+    }
   },
 
   created() {
diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue
index a0cd446abded78b8bc41a6cc956d65f3ee7fa81b..52a6604639da7a6468a906ba2079452451a08cd7 100644
--- a/src/views/project/Project_detail.vue
+++ b/src/views/project/Project_detail.vue
@@ -745,8 +745,10 @@ export default {
 
   computed: {
     ...mapGetters([
-      'project',
-      'permissions',
+      'permissions'
+    ]),
+    ...mapGetters('projects', [
+      'project'
     ]),
     ...mapState('feature_type', [
       'feature_types',
@@ -811,8 +813,11 @@ export default {
 
     if (this.user) {
       projectAPI
-        .getProjectSubscription({ projectSlug: this.$route.params.slug })
-        .then((data) => (this.is_suscriber = data.is_suscriber));
+        .getProjectSubscription({
+          baseUrl: this.$store.state.configuration.VUE_APP_DJANGO_API_BASE,
+          projectSlug: this.$route.params.slug
+        })
+          .then((data) => (this.is_suscriber = data.is_suscriber));
     }
     this.$store.commit("feature/SET_FEATURES", []); //* empty features remaining in case they were in geojson format and will be fetch after map initialization anyway
     this.$store.commit("feature_type/SET_FEATURE_TYPES", []); //* empty feature_types remaining from previous project
@@ -1029,6 +1034,7 @@ export default {
     subscribeProject() {
       projectAPI
         .subscribeProject({
+          baseUrl: this.$store.state.configuration.VUE_APP_DJANGO_API_BASE,
           suscribe: !this.is_suscriber,
           projectSlug: this.$route.params.slug,
         })
diff --git a/src/views/project/Project_edit.vue b/src/views/project/Project_edit.vue
index 715b5c8cbe2492ca7e17d8a1c745c2d631221038..f8ad6836291f32b91d8060c5b17d6c57ab0218d4 100644
--- a/src/views/project/Project_edit.vue
+++ b/src/views/project/Project_edit.vue
@@ -207,7 +207,7 @@
 import axios from '@/axios-client.js';
 import Dropdown from "@/components/Dropdown.vue";
 
-import { mapState, mapGetters } from "vuex";
+import { mapState, mapGetters, mapActions } from "vuex";
 
 export default {
   name: "Project_edit",
@@ -302,6 +302,9 @@ export default {
   },
 
   methods: {
+    ...mapActions('projects', [
+      'GET_ALL_PROJECTS'
+    ]),
     definePageType() {
       if (this.$router.history.current.name === "project_create") {
         this.action = "create";
@@ -381,7 +384,7 @@ export default {
       Promise.all([
         this.$store.dispatch("GET_USER_LEVEL_PROJECTS"), //* refresh projects user levels
         this.$store.dispatch("GET_USER_LEVEL_PERMISSIONS"), //* refresh projects permissions
-        this.$store.dispatch("GET_ALL_PROJECTS"), //* & refresh project list
+        this.GET_ALL_PROJECTS(), //* & refresh project list
       ]).then(() =>
         // * go back to project list
         this.$router.push({