diff --git a/components/badge/Date.vue b/components/badge/Date.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dccb6400457d32500e8acd34b0682781aa2019a3
--- /dev/null
+++ b/components/badge/Date.vue
@@ -0,0 +1,24 @@
+<template>
+	<small>
+        <span
+            class="badge"
+            :class="'badge-' + $options.filters.dateStatus(date)">
+            {{ $d(new Date(date * 1000), styleDate) }}
+        </span>
+    </small>
+</template>
+
+<script>
+export default {
+	props: {
+		date: {
+			type: Number,
+			required: true
+		},
+		styleDate: {
+			type: String,
+			required: true
+		},
+    }
+}
+</script>
diff --git a/components/certif/List.vue b/components/certif/List.vue
index 7146b8c55362581bd5881b2871f13abab403507b..03abdc2266011756a459b44f9d0c6cdab032434c 100644
--- a/components/certif/List.vue
+++ b/components/certif/List.vue
@@ -34,20 +34,12 @@
 						</div>
 					</th>
 					<td class="text-right py-1">
-						<small
-							><span
-								class="badge"
-								:class="
-									'badge-' + $options.filters.dateStatus(certif.expires_on)
-								"
-								>{{ $d(new Date(certif.expires_on * 1000), "short") }}</span
-							></small
-						>
-						<small class="d-block"
-							><span class="badge badge-secondary">{{
-								$t("traitement")
-							}}</span></small
-						>
+						<BadgeDate
+							:date="certif.expires_on"
+							:styleDate="'short'" />
+						<small class="d-block">
+							<span class="badge badge-secondary">{{ $t("traitement")}}</span>
+						</small>
 					</td>
 				</tr>
 			</tbody>
@@ -134,15 +126,9 @@
 						</div>
 					</th>
 					<td class="text-right py-1">
-						<small
-							><span
-								class="badge"
-								:class="
-									'badge-' + $options.filters.dateStatus(certif.expires_on)
-								"
-								>{{ $d(new Date(certif.expires_on * 1000), "long") }}</span
-							></small
-						>
+						<BadgeDate
+							:date="certif.expires_on"
+							:styleDate="'long'" />
 					</td>
 				</tr>
 			</tbody>
diff --git a/components/member/List.vue b/components/member/List.vue
index c6137ee28e32a2896c24ba987d4b087ea325d5f7..1ed5ac898a1c48259f0db25cbd4daa693665c91e 100644
--- a/components/member/List.vue
+++ b/components/member/List.vue
@@ -3,10 +3,52 @@
 		<table class="table table-striped table-hover">
 			<thead v-if="displayHead">
 				<tr>
-					<th scope="col">UID</th>
-					<th scope="col" class="d-none d-xl-table-cell" v-if="displayPubkey">
+					<th scope="col" @click="sort('uid')">
+						UID
+						<div class="d-inline-block position-absolute ml-2">
+							<div
+								class="up"
+								:class="{
+									sorted: currentSortDir == 'desc' && currentSort == 'uid',
+									invisible: currentSortDir == 'asc' && currentSort == 'uid'
+								}">
+								â–²
+							</div>
+							<div
+								class="down"
+								:class="{
+									sorted: currentSortDir == 'asc' && currentSort == 'uid',
+									invisible: currentSortDir == 'desc' && currentSort == 'uid'
+								}">
+								â–¼
+							</div>
+						</div>
+					</th>
+					<th scope="col" class="d-none d-xl-table-cell" v-if="displayPubkey && !displayOnlyDate">
 						{{ $t("cle.publique.title") }}
 					</th>
+					<th scope="col" class="d-none d-xl-table-cell"
+						@click="sort('limit_date')" v-if="displayOnlyDate">
+						{{ $t("limitDate") }}
+						<div class="d-inline-block position-absolute ml-2">
+							<div
+								class="up"
+								:class="{
+									sorted: currentSortDir == 'desc' && currentSort == 'limit_date',
+									invisible: currentSortDir == 'asc' && currentSort == 'limit_date'
+								}">
+								â–²
+							</div>
+							<div
+								class="down"
+								:class="{
+									sorted: currentSortDir == 'asc' && currentSort == 'limit_date',
+									invisible: currentSortDir == 'desc' && currentSort == 'limit_date'
+								}">
+								â–¼
+							</div>
+						</div>
+					</th>
 					<th scope="col" class="d-none d-sm-table-cell" v-if="displayDate">
 						{{ $t("membre.datelimpertestatut") }}
 					</th>
@@ -14,7 +56,7 @@
 			</thead>
 			<tbody>
 				<tr
-					v-for="member in members"
+					v-for="member in membersSorted"
 					:key="member.uid"
 					@click="redirect(member.hash)">
 					<th scope="row">
@@ -23,9 +65,15 @@
 							:limitDate="
 								Math.min(member.received_certifications.limit, member.limitDate)
 							"
-							:memberStatus="member.status" />
-						<BadgeStatus :membre="member" />
+							:memberStatus="member.status"
+							v-if="!displayOnlyDate" />
+						<BadgeStatus :membre="member" v-if="!displayOnlyDate"/>
 					</th>
+					<td class="d-none d-xl-table-cell" v-if="displayOnlyDate">
+						<BadgeDate
+							:date="adhesion ? member.limitDate : member.received_certifications.limit"
+							:styleDate="'long'" />
+					</td>
 					<td class="d-none d-xl-table-cell" v-if="displayPubkey">
 						{{ member.pubkey.substring(0, 10) }}
 					</td>
@@ -41,6 +89,12 @@
 
 <script>
 export default {
+	data() {
+		return {
+			currentSort: "uid",
+			currentSortDir: "asc"
+		}
+	},
 	props: {
 		members: {
 			type: Array,
@@ -57,7 +111,15 @@ export default {
 		displayDate: {
 			type: Boolean,
 			default: true
-		}
+		},
+		displayOnlyDate: {
+			type: Boolean,
+			default: false
+		},
+		adhesion: {
+			type: Boolean,
+			default: true
+		},
 	},
 	methods: {
 		redirect(hash) {
@@ -77,7 +139,64 @@ export default {
 						"'>" +
 						this.$d(new Date(date * 1000), "long") +
 						"</span>"
+		},
+		sort(s) {
+			if (s === this.currentSort) {
+				this.currentSortDir = this.currentSortDir === "asc" ? "desc" : "asc"
+			}
+			this.currentSort = s
+		}
+	},
+	computed: {
+		membersSorted() {
+			return this.members
+				.slice()
+				.sort((a, b) => {
+					let modifier = this.currentSortDir === "desc" ? -1 : 1
+
+					if (this.currentSort == "limit_date") {
+						if(this.adhesion) {
+							if (a["limitDate"] < b["limitDate"]) return -1 * modifier
+							if (a["limitDate"] > b["limitDate"]) return 1 * modifier
+						} else {
+							if (a["received_certifications"]["limit"] < b["received_certifications"]["limit"]) return -1 * modifier
+							if (a["received_certifications"]["limit"] > b["received_certifications"]["limit"]) return 1 * modifier
+						}
+					} else {
+						if (a["uid"].toLowerCase() < b["uid"].toLowerCase())
+							return -1 * modifier
+						if (a["uid"].toLowerCase() > b["uid"].toLowerCase())
+							return 1 * modifier
+					}
+
+					return 0
+				})
 		}
 	}
 }
 </script>
+
+<style lang="scss" scoped>
+thead th {
+	position: relative;
+	cursor: pointer;
+	background: var(--background-color-secondary);
+
+	&:last-child {
+		padding-right: 1.5rem;
+		text-align: right;
+	}
+}
+
+.up,
+.down {
+	line-height: 10px;
+	font-size: 1.1rem;
+	transform: scale(1.5, 1);
+	opacity: 0.3;
+}
+
+.sorted {
+	opacity: 1;
+}
+</style>
diff --git a/graphql/doc/graphQLschema.txt b/graphql/doc/graphQLschema.txt
index a4ce243ccb6e89b62c274c3c6a4fe0943bd8558d..bfa30d15060df51340fb233c1474d26bb420f0a6 100644
--- a/graphql/doc/graphQLschema.txt
+++ b/graphql/doc/graphQLschema.txt
@@ -595,7 +595,7 @@ type Forecast {
 "Entry or exit of an identity"
 type EventId {
 	
-	id: Identity!
+	member: Identity!
 	
 	"Entry or exit; true if entry"
 	inOut: Boolean!
diff --git a/graphql/queries.js b/graphql/queries.js
index 3585f5be469180649efb8a69e8a48d8b4518cc70..1aae22226bd331751aad2f95e26e1c6329d6c4e0 100644
--- a/graphql/queries.js
+++ b/graphql/queries.js
@@ -206,3 +206,21 @@ export const FAVORIS = gql`
 		}
 	}
 `
+
+// Pour la page index
+export const NEXT_EXITS = gql`
+	query NextExits($group: [String!], $start: Int64, $period: Int64) {
+		memEnds (group: $group, startFromNow: $start, period: $period) {
+			__typename
+			pubkey
+			uid
+			status
+			hash
+			limitDate
+			received_certifications {
+				__typename
+				limit
+			}
+		}
+	}
+`
diff --git a/i18n/locales/en.json b/i18n/locales/en.json
index 2d2967b2de30b0f203fd033b80171ccdb3ca5c63..bcce32286f9e2dfe5e0e1d4aa055dd57726c59a5 100644
--- a/i18n/locales/en.json
+++ b/i18n/locales/en.json
@@ -62,6 +62,10 @@
 		"title": "Duniter"
 	},
 	"expire": "Expires",
+	"error": {
+		"tooSmall": "{0} is too small. It must be between {1} and {2}. The value used is {1}",
+		"tooBig": "{0} is too big. It must be between {1} and {2}. The value used is {1}"
+	},
 	"favoris": {
 		"enregistre": "Saved to favorites&nbsp;!",
 		"none": "You don't have any favorites yet",
@@ -69,10 +73,12 @@
 		"title": "My favourites"
 	},
 	"futuremembers": "Future members",
+	"futureexits": "Future exits",
 	"infos": "Informations",
 	"inout": "Entries and exits of the web of trust for the last 2 days",
 	"inpreparation": "In preparation",
 	"lexique": "Lexicon",
+	"limitDate": "Deadline",
 	"membre": {
 		"calculant": {
 			"desc": "Member using his private key to forge blocks thanks to Duniter installed on a node accessible on the Internet network",
@@ -150,8 +156,13 @@
 	"previsions": {
 		"pardate": "Forecasts by dates",
 		"parmembre": "Forecasts by members",
+		"period": {
+			"title": "Search period",
+			"desc": "Select the desired number of days between 1 and 30"
+		},
 		"title": "Forecasts"
 	},
+	"pubkey": "Public key",
 	"recherche": {
 		"desc": "Enter the start of a nickname or public key",
 		"title": "Your search"
@@ -184,6 +195,7 @@
 		"title": "Relative Theory of Money (RTM)"
 	},
 	"type": "Type",
+	"uid": "Unique identifier",
 	"valeur": "Value",
 	"wot": {
 		"desc": "Set of the individuals recognized as such by their peers including the links that bind them together through certifications",
diff --git a/i18n/locales/es.json b/i18n/locales/es.json
index 158f517d3b89e09cabd5c032f4d7f265bbdfe0df..bc350951643454b85c70a8ddb7d11d42ad94725e 100644
--- a/i18n/locales/es.json
+++ b/i18n/locales/es.json
@@ -62,6 +62,10 @@
 		"title": "Duniter"
 	},
 	"expire": "Expira el",
+	"error": {
+		"tooSmall": "{0} es demasiado pequeño. Debe estar entre {1} y {2}. El valor utilizado es {1}",
+		"tooBig": "{0} es demasiado grande. Debe estar entre {1} y {2}. El valor utilizado es {1}"
+	},
 	"favoris": {
 		"enregistre": "¡Guardado en favoritos!",
 		"none": "Aún no tienes favoritos",
@@ -69,10 +73,12 @@
 		"title": "Mis favoritos"
 	},
 	"futuremembers": "Futuros miembros",
+	"futureexits": "Futuras salidas",
 	"infos": "Informaciones",
 	"inout": "Entradas y salidas de la red de confianza en los últimos 2 días",
 	"inpreparation": "En preparación",
 	"lexique": "Léxico",
+	"limitDate": "Fecha límite",
 	"membre": {
 		"calculant": {
 			"desc": "Miembro usando su clave privada para falsificar bloques gracias a Duniter instalado en un nodo accesible en la red de Internet",
@@ -150,8 +156,13 @@
 	"previsions": {
 		"pardate": "Previsiones por fecha",
 		"parmembre": "Previsiones por miembros",
+		"period": {
+			"title": "Período de búsqueda",
+			"desc": "Seleccione el número de días deseado entre 1 y 30"
+		},
 		"title": "Pronósticos"
 	},
+	"pubkey": "Llave pública",
 	"recherche": {
 		"desc": "Introduce el comienzo de un pseudónimo o llave pública",
 		"title": "Buscar"
@@ -184,6 +195,7 @@
 		"title": "Teoría relativa del dinero (TRD)"
 	},
 	"type": "Tipo",
+	"uid": "Identificador único",
 	"valeur": "Valor",
 	"wot": {
 		"desc": "Conjunto de las personas reconocidas como tales por sus pares incluyendo los vínculos que las unen a través de certificaciones",
diff --git a/i18n/locales/fr.json b/i18n/locales/fr.json
index 043e0e242e2c05130a71c39a1b7468bcced64a64..bafd341e6e9b85ec2516ca1bdf7d3f7c9421e85f 100644
--- a/i18n/locales/fr.json
+++ b/i18n/locales/fr.json
@@ -62,6 +62,10 @@
 		"title": "Duniter"
 	},
 	"expire": "Expire le",
+	"error": {
+		"tooSmall": "{0} est trop petit. Il doit être compris entre {1} et {2}. La valeur utilisée est {1}",
+		"tooBig": "{0} est trop grand. Il doit être compris entre {1} et {2}. La valeur utilisée est {2}"
+	},
 	"favoris": {
 		"enregistre": "Enregistré dans les favoris&nbsp;!",
 		"none": "Vous n'avez pas encore de favoris",
@@ -69,10 +73,12 @@
 		"title": "Mes favoris"
 	},
 	"futuremembers": "Futurs membres",
+	"futureexits": "Futures sorties",
 	"infos": "Informations",
 	"inout": "Entrées et sorties de la toile de confiance des 2 derniers jours",
 	"inpreparation": "En préparation",
 	"lexique": "Lexique",
+	"limitDate": "Date limite",
 	"membre": {
 		"calculant": {
 			"desc": "Membre utilisant sa clé privée pour forger des blocs grâce à Duniter installé sur un noeud accessible sur le réseau Internet",
@@ -150,8 +156,13 @@
 	"previsions": {
 		"pardate": "Prévisions par date",
 		"parmembre": "Prévisions par membres",
+		"period": {
+			"title": "Période de recherche",
+			"desc": "Sélectionnez le nombre de jours souhaités entre 1 et 30"
+		},
 		"title": "Prévisions"
 	},
+	"pubkey": "Clef publique",
 	"recherche": {
 		"desc": "Saisissez le début d'un pseudo ou d'une clé publique",
 		"title": "Votre recherche"
@@ -184,6 +195,7 @@
 		"title": "Théorie Relative de la Monnaie (TRM)"
 	},
 	"type": "Type",
+	"uid": "Identifiant unique",
 	"valeur": "Valeur",
 	"wot": {
 		"desc": "Ensemble des membres et des certifications qui les relient entre eux",
diff --git a/layouts/default.vue b/layouts/default.vue
index 651572ffc0ca15a236d8ca5dedb4809645c36ad2..6061a0cbb5811cd2db9e76f7b7760d9697f4143c 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -21,7 +21,10 @@ export default {
 				},
 				{
 					title: "previsions.title",
-					items: [{ path: "/previsions", title: "futuremembers" }]
+					items: [
+						{ path: "/previsions", title: "futuremembers" },
+						{ path: "/previsions/futures_sorties", title: "futureexits" },
+					]
 				},
 				{
 					title: "infos",
diff --git a/pages/previsions/futures_sorties.vue b/pages/previsions/futures_sorties.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ef8adfb4fe125b16586007ce0505547999b9b4bc
--- /dev/null
+++ b/pages/previsions/futures_sorties.vue
@@ -0,0 +1,169 @@
+<template>
+	<main class="container">
+		<h2 class="text-center my-5 font-weight-light">{{ $t("futureexits") }}</h2>
+		<div class="row mb-4">
+			<div class="col-6 m-auto text-center">
+				<label for="period" class="form-label">{{ $t("previsions.period.title") }}</label>
+				<input
+					type="number"
+					class="form-control"
+					:class="{ invalid:periodIsInvalid() }"
+					id="period"
+					aria-describedby="periodHelp"
+					v-model="period"
+					autocomplete="off"
+					min="1" max="30"
+					@keyup="save" />
+				<small id="periodHelp" class="form-text text-muted">{{ $t("previsions.period.desc") }}</small>
+			</div>
+		</div>
+		<NavigationLoader :isLoading="$apollo.queries.wwResult.loading" />
+		<transition name="fade">
+			<div class="alert alert-danger" v-if="error && !$apollo.queries.wwResult.loading">{{ error }}</div>
+		</transition>
+		<transition name="fade">
+			<div v-if="wwResult && !$apollo.queries.wwResult.loading">
+				<div class="row text-center">
+					<div class="col-md-6 col-lg-6">
+						<h2 class="h4 text-danger">{{ $t("statut.renew") }}</h2>
+						<MemberList
+							:members="wwResult['membership']"
+							:displayPubkey="false"
+							:displayOnlyDate="true"
+							:displayDate="false" />
+					</div>
+					<div class="col-md-6 col-lg-6">
+						<h2 class="h4 text-danger">{{ $t("statut.manquecertif") }}</h2>
+						<MemberList
+							:members="wwResult['outOfCerts']"
+							:displayPubkey="false"
+							:displayOnlyDate="true"
+							:displayDate="false"
+							:adhesion="false" />
+					</div>
+				</div>
+			</div>
+		</transition>
+	</main>
+</template>
+
+<script>
+import { NEXT_EXITS } from "@/graphql/queries.js"
+
+const day = 24*60*60
+const defaultPeriod = 30*day
+
+export default {
+  	data() {
+		return {
+			breadcrumb: [
+				{
+					text: this.$t('accueil'),
+					to: '/'
+				},
+				{
+					text: this.$t('previsions.title'),
+					to: '/previsions'
+				},
+				{
+					text: this.$t('futureexits'),
+					active: true
+				}
+			],
+			error: null,
+			period: 30,
+			display: 'forecastsByNames'
+		}
+	},
+	methods: {
+		save() {
+			this.error = null
+			localStorage.setItem('previsions_sorties', this.display)
+			localStorage.setItem('previsions_period', this.getPeriod()/day)
+		},
+		addValue(arr, val) {
+			if (
+				arr.filter(function (e) {
+					return e.uid === val.uid
+				}).length == 0
+			) {
+				arr.push(val)
+			}
+			return arr
+		},
+		getPeriod() {
+			if( this.period != "") {
+				let tempPeriod = parseInt(this.period)
+				if(tempPeriod < 1) {
+					this.error = this.$t("error.tooSmall", [ tempPeriod, 1, 30 ])
+					return day
+				}
+				if(tempPeriod > 30) {
+					this.error = this.$t('error.tooBig', [ tempPeriod, 1, 30 ])
+					return 30 * day
+				}
+				return this.period*day
+			}
+			return defaultPeriod
+		},
+		periodIsInvalid() {
+			return this.period != "" && (this.period < 1 || this.period > 30)
+		}
+	},
+	apollo: {
+		wwResult : {
+			query: NEXT_EXITS,
+			variables() {
+				return { period: this.getPeriod()}
+			},
+			update (data) {
+				let result = { membership: [], outOfCerts: [] }
+
+				for (let i = 0; i < data.memEnds.length; i++) {
+					let identity = data.memEnds[i]
+					if(['danger', 'warning'].includes(this.$options.filters.dateStatus(identity.limitDate))) {
+						this.addValue(result["membership"], identity)
+					}
+					if(['danger', 'warning'].includes(this.$options.filters.dateStatus(identity.received_certifications.limit))) {
+						this.addValue(result["outOfCerts"], identity)
+					}
+				}
+				return result
+			},
+			error (err) {this.error = err.message}
+		}
+	},
+	nuxtI18n: {
+		paths: {
+			fr: '/previsions/futures_sorties',
+			en: '/forecasts/future_exits',
+			es: '/pronosticos/futuras_salidas'
+		}
+	},
+	mounted () {
+		$nuxt.$emit('changeRoute',this.breadcrumb)
+		if (localStorage.previsions_sorties) {
+			this.display = localStorage.getItem('previsions_sorties')
+			this.period = localStorage.getItem('previsions_period')
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.list-group-item {
+	background: transparent;
+	&:hover {
+		background: rgba(0, 0, 255, 0.075);
+		color: var(--text-primary-color);
+	}
+}
+
+.forecast_date {
+	min-width: 150px;
+}
+
+.invalid {
+	border: 4px solid #ec0404;
+}
+</style>