diff --git a/front/src/components/requests/Card.vue b/front/src/components/requests/Card.vue
new file mode 100644
index 0000000000000000000000000000000000000000..deb9c3fe093a58cc6913805ad4fcbe9bed4da58d
--- /dev/null
+++ b/front/src/components/requests/Card.vue
@@ -0,0 +1,61 @@
+<template>
+  <div :class="['ui', {collapsed: collapsed}, 'card']">
+    <div class="content">
+      <div class="header">{{ request.artist_name }}</div>
+      <div class="description">
+        <div
+          v-if="request.albums" v-html="$options.filters.markdown(request.albums)"></div>
+        <div v-if="request.comment" class="ui comments">
+          <comment
+            :user="request.user"
+            :content="request.comment"
+            :date="request.creation_date"></comment>
+        </div>
+      </div>
+    </div>
+    <div class="extra content">
+      <span >
+        <i v-if="request.status === 'pending'" class="hourglass start icon"></i>
+        <i v-if="request.status === 'accepted'" class="hourglass half icon"></i>
+        <i v-if="request.status === 'imported'" class="check icon"></i>
+        {{ request.status | capitalize }}
+      </span>
+      <button
+        @click="createImport"
+        v-if="request.status === 'pending' && importAction && $store.state.auth.availablePermissions['import.launch']"
+        class="ui mini basic green right floated button">Create import</button>
+      
+    </div>
+  </div>
+</template>
+
+<script>
+import Comment from '@/components/discussion/Comment'
+
+export default {
+  props: {
+    request: {type: Object, required: true},
+    importAction: {type: Boolean, default: true}
+  },
+  components: {
+    Comment
+  },
+  data () {
+    return {
+      collapsed: true
+    }
+  },
+  methods: {
+    createImport () {
+      this.$router.push({
+        name: 'library.import.launch',
+        query: {request: this.request.id}})
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+</style>
diff --git a/front/src/components/requests/RequestsList.vue b/front/src/components/requests/RequestsList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cb3e9af00bc40d0301b23dcb446576a567e7f153
--- /dev/null
+++ b/front/src/components/requests/RequestsList.vue
@@ -0,0 +1,163 @@
+<template>
+  <div>
+    <div class="ui vertical stripe segment">
+      <h2 class="ui header">Music requests</h2>
+      <div :class="['ui', {'loading': isLoading}, 'form']">
+        <div class="fields">
+          <div class="field">
+            <label>Search</label>
+            <input type="text" v-model="query" placeholder="Enter an artist name, a username..."/>
+          </div>
+          <div class="field">
+            <label>Ordering</label>
+            <select class="ui dropdown" v-model="ordering">
+              <option v-for="option in orderingOptions" :value="option[0]">
+                {{ option[1] }}
+              </option>
+            </select>
+          </div>
+          <div class="field">
+            <label>Ordering direction</label>
+            <select class="ui dropdown" v-model="orderingDirection">
+              <option value="">Ascending</option>
+              <option value="-">Descending</option>
+            </select>
+          </div>
+          <div class="field">
+            <label>Results per page</label>
+            <select class="ui dropdown" v-model="paginateBy">
+              <option :value="parseInt(12)">12</option>
+              <option :value="parseInt(25)">25</option>
+              <option :value="parseInt(50)">50</option>
+            </select>
+          </div>
+        </div>
+      </div>
+      <div class="ui hidden divider"></div>
+      <div v-if="result" class="ui stackable three column grid">
+        <div
+          v-if="result.results.length > 0"
+          v-for="request in result.results"
+          :key="request.id"
+          class="column">
+          <request-card class="fluid" :request="request"></request-card>
+        </div>
+      </div>
+      <div class="ui center aligned basic segment">
+        <pagination
+          v-if="result && result.results.length > 0"
+          @page-changed="selectPage"
+          :current="page"
+          :paginate-by="paginateBy"
+          :total="result.count"
+          ></pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+import _ from 'lodash'
+import $ from 'jquery'
+
+import logger from '@/logging'
+
+import OrderingMixin from '@/components/mixins/Ordering'
+import PaginationMixin from '@/components/mixins/Pagination'
+import RequestCard from '@/components/requests/Card'
+import Pagination from '@/components/Pagination'
+
+const FETCH_URL = 'requests/import-requests/'
+
+export default {
+  mixins: [OrderingMixin, PaginationMixin],
+  props: {
+    defaultQuery: {type: String, required: false, default: ''}
+  },
+  components: {
+    RequestCard,
+    Pagination
+  },
+  data () {
+    let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || '-creation_date')
+    return {
+      isLoading: true,
+      result: null,
+      page: parseInt(this.defaultPage),
+      query: this.defaultQuery,
+      paginateBy: parseInt(this.defaultPaginateBy || 12),
+      orderingDirection: defaultOrdering.direction,
+      ordering: defaultOrdering.field,
+      orderingOptions: [
+        ['creation_date', 'Creation date'],
+        ['artist_name', 'Artist name'],
+        ['user__username', 'User']
+      ]
+    }
+  },
+  created () {
+    this.fetchData()
+  },
+  mounted () {
+    $('.ui.dropdown').dropdown()
+  },
+  methods: {
+    updateQueryString: _.debounce(function () {
+      this.$router.replace({
+        query: {
+          query: this.query,
+          page: this.page,
+          paginateBy: this.paginateBy,
+          ordering: this.getOrderingAsString()
+        }
+      })
+    }, 500),
+    fetchData: _.debounce(function () {
+      var self = this
+      this.isLoading = true
+      let url = FETCH_URL
+      let params = {
+        page: this.page,
+        page_size: this.paginateBy,
+        search: this.query,
+        ordering: this.getOrderingAsString()
+      }
+      logger.default.debug('Fetching request...')
+      axios.get(url, {params: params}).then((response) => {
+        self.result = response.data
+        self.isLoading = false
+      })
+    }, 500),
+    selectPage: function (page) {
+      this.page = page
+    }
+  },
+  watch: {
+    page () {
+      this.updateQueryString()
+      this.fetchData()
+    },
+    paginateBy () {
+      this.updateQueryString()
+      this.fetchData()
+    },
+    ordering () {
+      this.updateQueryString()
+      this.fetchData()
+    },
+    orderingDirection () {
+      this.updateQueryString()
+      this.fetchData()
+    },
+    query () {
+      this.updateQueryString()
+      this.fetchData()
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+</style>
diff --git a/front/src/router/index.js b/front/src/router/index.js
index bf59b8ee86213029611624ef9cc2cb62bc355d7d..ea8854bbe48e4f06ec4369a2853b3e98271df733 100644
--- a/front/src/router/index.js
+++ b/front/src/router/index.js
@@ -17,6 +17,7 @@ import LibraryRadios from '@/components/library/Radios'
 import RadioBuilder from '@/components/library/radios/Builder'
 import BatchList from '@/components/library/import/BatchList'
 import BatchDetail from '@/components/library/import/BatchDetail'
+import RequestsList from '@/components/requests/RequestsList'
 
 import Favorites from '@/components/favorites/List'
 
@@ -100,6 +101,7 @@ export default new Router({
           component: LibraryImport,
           props: (route) => ({
             source: route.query.source,
+            request: route.query.request,
             mbType: route.query.type,
             mbId: route.query.id })
         },
@@ -110,7 +112,21 @@ export default new Router({
           children: [
           ]
         },
-        { path: 'import/batches/:id', name: 'library.import.batches.detail', component: BatchDetail, props: true }
+        { path: 'import/batches/:id', name: 'library.import.batches.detail', component: BatchDetail, props: true },
+        {
+          path: 'requests/',
+          name: 'library.requests',
+          component: RequestsList,
+          props: (route) => ({
+            defaultOrdering: route.query.ordering,
+            defaultQuery: route.query.query,
+            defaultPaginateBy: route.query.paginateBy,
+            defaultPage: route.query.page,
+            defaultStatus: route.query.status || 'pending'
+          }),
+          children: [
+          ]
+        }
       ]
     },
     { path: '*', component: PageNotFound }