diff --git a/app/views/messages/overview.php b/app/views/messages/overview.php
index 6e39e0d9a202da1b0d20d9c75255181ccca4c5e8..c514eb66fea5bf7b4b9a724ea0bef46ad51032bc 100644
--- a/app/views/messages/overview.php
+++ b/app/views/messages/overview.php
@@ -1,3 +1,9 @@
+<div data-vue-app='<?= json_encode(['components' => ['MessagesList']]) ?>'>
+    vue
+    <messages-list type="<?= $received ? 'inbox' : 'outbox' ?>" />
+    app
+</div>
+
 <input type="hidden" name="received" id="received" value="<?= (int) $received ?>">
 <input type="hidden" name="since" id="since" value="<?= time() ?>">
 <input type="hidden" name="folder_id" id="tag" value="<?= htmlReady(ucfirst(Request::get("tag"))) ?>">
diff --git a/resources/vue/components/MessagesList.vue b/resources/vue/components/MessagesList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..febcdffb09cd62a43f885c8c7814c22cc998b823
--- /dev/null
+++ b/resources/vue/components/MessagesList.vue
@@ -0,0 +1,133 @@
+<template>
+    <table class="default">
+        <caption>{{ messageListName }}</caption>
+        <colgroup>
+            <col class="hidden-small-down">
+            <col>
+            <col class="hidden-small-down">
+            <col style="width: 20ex">
+            <col class="hidden-small-down">
+        </colgroup>
+        <thead>
+            <tr>
+                <th>
+
+                </th>
+                <th>
+                    <translate>Betreff</translate>
+                </th>
+                <th>
+                    <translate>Absender</translate>
+                </th>
+                <th>
+                    <translate>Zeit</translate>
+                </th>
+                <th>
+                    <translate>Schlagworte</translate>
+                </th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr v-for="message in messages">
+                <td></td>
+                <td>{{ message.subject }}</td>
+                <td v-if="type === 'inbox'">
+                    {{ getUser(message.sender)['formatted-name'] }}
+                </td>
+                <td v-else></td>
+                <td>
+                    {{ showDate(message.mkdate) }}
+                </td>
+                <td>
+                    <ul class="list-csv" v-if="message.tags.length > 0">
+                        <li v-for="tag in message.tags">
+                            {{ tag }}
+                        </li>
+                    </ul>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</template>
+<script>
+export default {
+    name: 'messages-list',
+    props: {
+        type: {
+            type: String,
+            required: true,
+            validator (value) {
+                return ['inbox', 'outbox'].includes(value);
+            }
+        }
+    },
+    data () {
+        return {
+            messages: [],
+            users: []
+        }
+    },
+    methods: {
+        getUser (userId) {
+            console.log('get user', userId);
+            if (userId === undefined) {
+                return {
+                    'formatted-name': this.$gettext('Systemnachricht')
+                };
+            }
+            return this.users.find(user => user.id === userId);
+        },
+        getMessageFromResponse (data) {
+            return Object.assign({}, data.attributes, {
+                id: data.id,
+                sender: data.relationships.sender?.data.id,
+                recipients: data.relationships.recipients.data.map(attributes => attributes.id),
+            });
+        },
+        getUserFromResponse (data) {
+            return Object.assign({}, data.attributes, data.meta,{
+                id: data.id,
+            });
+        },
+        showDate (date) {
+            const jsDate = new Date(date);
+            return jsDate.toLocaleString(String.locale, {
+                day: '2-digit',
+                month: '2-digit',
+                year: 'numeric',
+                hour: '2-digit',
+                minute: '2-digit'
+            });
+        }
+    },
+    computed: {
+        messageListName () {
+            return this.type === 'inbox' ? this.$gettext('Eingang') : this.$gettext('Ausgang');
+        }
+    },
+    created () {
+        let include = [];
+        if (this.type === 'inbox') {
+            include.push('sender');
+        } else {
+            include.push('recipients');
+        }
+
+        const userId = STUDIP.USER_ID;
+        STUDIP.jsonapi.GET(`users/${userId}/${this.type}?include=${include.join(',')}`).then(response => {
+            response.included.filter(item => item.type === 'users').forEach(user => {
+                this.users.push(this.getUserFromResponse(user));
+            });
+
+            if (response.data && response.data.length > 0) {
+                response.data.forEach(message => {
+                    console.log('push message');
+                    this.messages.push(this.getMessageFromResponse(message));
+                })
+            }
+
+            console.log('response', response);
+        });
+    }
+}
+</script>