diff --git a/src/membershipTool.js b/src/membershipTool.js
new file mode 100644
index 0000000000000000000000000000000000000000..e662be97fd7650851467fd08dd3c9ac8808cce97
--- /dev/null
+++ b/src/membershipTool.js
@@ -0,0 +1,39 @@
+import EditView from './views/editView';
+import SelectList from './views/selectList';
+
+const m = require('mithril');
+
+export class MembershipView extends EditView {
+  constructor(vnode) {
+    super(vnode, 'groupmemberships', { user: 1, group: 1 });
+  }
+
+  view() {
+    // do not render anything if there is no data yet
+    if (!this.data) return m.trust('');
+
+    return m('div', [
+      m('h1', `${this.data.user.firstname} ${this.data.user.lastname}`),
+      m('br'),
+      m('strong', 'is member in'),
+      m('br'),
+      m('h1', this.data.group.name),
+      m('br'),
+      m('span', this.data.expiry),
+    ]);
+  }
+}
+
+export class NewMembership {
+  constructor() {
+    this.selectUser = new SelectList('users', ['firstname', 'lastname'], {
+      view(vnode) {
+        return m('span', `${vnode.attrs.firstname} ${vnode.attrs.lastname}`);
+      },
+    });
+  }
+
+  view() {
+    return m(this.selectUser);
+  }
+}