diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index dc13c4f9b0c7a02e23abf0efd9a40dcf5c26a021..ebe8d9d8f2bb16f48f45598e5e7676482c4e4284 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -56,7 +56,7 @@ module.exports = {
         test: /\.js$/,
         loader: 'babel',
         include: projectRoot,
-        exclude: /node_modules/
+        exclude: /node_modules\/(?!tributejs)/
       },
       {
         test: /\.json$/,
diff --git a/package.json b/package.json
index b5163e8231c906181866161d8d2fe161c174cec9..3832113437771227dcd7dc4d0f817cd05bcdd153 100644
--- a/package.json
+++ b/package.json
@@ -13,11 +13,13 @@
     "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
   },
   "dependencies": {
+    "babel-plugin-add-module-exports": "^0.2.1",
     "diff": "^3.0.1",
     "karma-mocha-reporter": "^2.2.1",
     "node-sass": "^3.10.1",
     "sanitize-html": "^1.13.0",
     "sass-loader": "^4.0.2",
+    "tributejs": "^2.1.0",
     "vue": "^2.0.1",
     "vue-router": "^2.0.1",
     "vue-timeago": "^3.1.2",
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index b17fdaa1f35025567dc526964ef7c037aa3b2ee4..650a9264f964a1b5f82fd95ed86d4b6d506964c5 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -1,8 +1,10 @@
 import statusPoster from '../../services/status_poster/status_poster.service.js'
 import MediaUpload from '../media_upload/media_upload.vue'
 import fileTypeService from '../../services/file_type/file_type.service.js'
+import Tribute from '../../../node_modules/tributejs/src/Tribute.js'
+require('../../../node_modules/tributejs/scss/tribute.scss')
 
-import { reject, map, uniqBy } from 'lodash'
+import { merge, reject, map, uniqBy } from 'lodash'
 
 const buildMentionsString = ({user, attentions}, currentUser) => {
   let allAttentions = [...attentions]
@@ -19,6 +21,51 @@ const buildMentionsString = ({user, attentions}, currentUser) => {
   return mentions.join(' ') + ' '
 }
 
+const defaultCollection = {
+  // symbol that starts the lookup
+  trigger: '@',
+
+  // element to target for @mentions
+  iframe: null,
+
+  // class added in the flyout menu for active item
+  selectClass: 'highlight',
+
+  // function called on select that returns the content to insert
+  selectTemplate: function (item) {
+    return '@' + item.original.screen_name
+  },
+
+  // template for displaying item in menu
+  menuItemTemplate: function (item) {
+    return `<img src="${item.original.profile_image_url}"></img> <div class='name'>${item.string}</div>`
+  },
+
+  // template for when no match is found (optional),
+  // If no template is provided, menu is hidden.
+  noMatchTemplate: null,
+
+  // specify an alternative parent container for the menu
+  menuContainer: document.body,
+
+  // column to search against in the object (accepts function or string)
+  lookup: 'name',
+
+  // column that contains the content to insert by default
+  fillAttr: 'screen_name',
+
+  // REQUIRED: array of objects to match
+  values: [],
+
+  // specify whether a space is required before the trigger character
+  requireLeadingSpace: true,
+
+  // specify whether a space is allowed in the middle of mentions
+  allowSpaces: false
+}
+
+const tribute = new Tribute({ collection: [] })
+
 const PostStatusForm = {
   props: [
     'replyTo',
@@ -44,6 +91,24 @@ const PostStatusForm = {
       }
     }
   },
+  computed: {
+    completions () {
+      let users = map(this.$store.state.statuses.allStatuses, 'user')
+      users = uniqBy(users, 'id')
+      users = merge({values: users}, defaultCollection)
+      return [users]
+    }
+  },
+  watch: {
+    completions () {
+      tribute.collection = this.completions
+    }
+  },
+  mounted () {
+    const textarea = this.$el.querySelector('textarea')
+    tribute.collection = this.completions
+    tribute.attach(textarea)
+  },
   methods: {
     postStatus (newStatus) {
       statusPoster.postStatus({
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index b18e5d8005fb1bae43583d676c227abc7ae91ff3..a6aaf511a22a8b369b30ff361c73f8bf29ba93f2 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -24,6 +24,22 @@
 <script src="./post_status_form.js"></script>
 
 <style lang="scss">
+ .tribute-container {
+   ul {
+     padding: 0px;
+     li {
+       display: flex;
+       align-items: center;
+     }
+   }
+   img {
+     padding: 3px;
+     width: 16px;
+     height: 16px;
+     border-radius: 50%;
+   }
+ }
+
  .post-status-form, .login {
      .form-bottom {
          display: flex;
diff --git a/yarn.lock b/yarn.lock
index d7fc2fec0668932b90bdcbe9c84a24563c8631a3..161506130f5ba0ed22b429b34189ea96ad9ad65f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -451,6 +451,10 @@ babel-messages@^6.8.0:
   dependencies:
     babel-runtime "^6.0.0"
 
+babel-plugin-add-module-exports:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
+
 babel-plugin-check-es2015-constants@^6.3.13:
   version "6.8.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7"
@@ -5482,6 +5486,10 @@ tough-cookie@~2.3.0:
   dependencies:
     punycode "^1.4.1"
 
+tributejs:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/tributejs/-/tributejs-2.1.0.tgz#2015cf2cd5fe0b7cb35f203bf67c5880bb9255d7"
+
 trim-newlines@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"