diff --git a/front/package.json b/front/package.json
index ac3895f6d65655fd198699c92cd55300df301b1e..042e332d0eb91d81df9c27fe13b82b0e16013d3a 100644
--- a/front/package.json
+++ b/front/package.json
@@ -20,9 +20,11 @@
     "js-logger": "^1.3.0",
     "jwt-decode": "^2.2.0",
     "lodash": "^4.17.4",
+    "moment": "^2.20.1",
     "moxios": "^0.4.0",
     "raven-js": "^3.22.3",
     "semantic-ui-css": "^2.2.10",
+    "showdown": "^1.8.6",
     "vue": "^2.3.3",
     "vue-lazyload": "^1.1.4",
     "vue-router": "^2.3.1",
diff --git a/front/src/filters.js b/front/src/filters.js
new file mode 100644
index 0000000000000000000000000000000000000000..7695046e44082ee423e13786e69c51c91bac9ad2
--- /dev/null
+++ b/front/src/filters.js
@@ -0,0 +1,31 @@
+import Vue from 'vue'
+
+import moment from 'moment'
+import showdown from 'showdown'
+
+export function truncate (str, max, ellipsis) {
+  max = max || 100
+  ellipsis = ellipsis || '…'
+  if (str.length <= max) {
+    return str
+  }
+  return str.slice(0, max) + ellipsis
+}
+
+Vue.filter('truncate', truncate)
+
+export function markdown (str) {
+  const converter = new showdown.Converter()
+  return converter.makeHtml(str)
+}
+
+Vue.filter('markdown', markdown)
+
+export function ago (date) {
+  const m = moment(date)
+  return m.fromNow()
+}
+
+Vue.filter('ago', ago)
+
+export default {}
diff --git a/front/src/main.js b/front/src/main.js
index d1ff90c3256846b65848021e1abf0f0b3fb19bc7..33e998ded96a7fed8efae2153c5eb091e17d0687 100644
--- a/front/src/main.js
+++ b/front/src/main.js
@@ -13,6 +13,7 @@ import VueLazyload from 'vue-lazyload'
 import store from './store'
 import config from './config'
 import { sync } from 'vuex-router-sync'
+import filters from '@/filters' // eslint-disable-line
 
 sync(store, router)
 
diff --git a/front/test/unit/specs/filters/filters.spec.js b/front/test/unit/specs/filters/filters.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..227d6c88b8db1746203ebeb10186c1317a4e2cc9
--- /dev/null
+++ b/front/test/unit/specs/filters/filters.spec.js
@@ -0,0 +1,35 @@
+import {truncate, markdown, ago} from '@/filters'
+
+describe('filters', () => {
+  describe('truncate', () => {
+    it('leave strings as it if correct size', () => {
+      const input = 'Hello world'
+      let output = truncate(input, 100)
+      expect(output).to.equal(input)
+    })
+    it('returns shorter string with character', () => {
+      const input = 'Hello world'
+      let output = truncate(input, 5)
+      expect(output).to.equal('Hello…')
+    })
+    it('custom ellipsis', () => {
+      const input = 'Hello world'
+      let output = truncate(input, 5, ' pouet')
+      expect(output).to.equal('Hello pouet')
+    })
+  })
+  describe('markdown', () => {
+    it('renders markdown', () => {
+      const input = 'Hello world'
+      let output = markdown(input)
+      expect(output).to.equal('<p>Hello world</p>')
+    })
+  })
+  describe('ago', () => {
+    it('works', () => {
+      const input = new Date()
+      let output = ago(input)
+      expect(output).to.equal('a few seconds ago')
+    })
+  })
+})