diff --git a/src/memberdb/register.py b/src/memberdb/register.py
index e2f648d80c7b5aa7b3dd6cf25e22290497d6a536..60f1ba38e8820a922afe2098a1089eea8baca7e0 100644
--- a/src/memberdb/register.py
+++ b/src/memberdb/register.py
@@ -107,7 +107,6 @@ def thanks_view(request, member, ms):
         'member': member,
         'ms': ms,
         'login_url': reverse('memberdb:login_member', kwargs={'username': member.username, 'member_token': member.login_token}),
-        'payment_url': reverse('squarepay:pay_membership', kwargs={'pk': ms.id}),
     }
     return render(request, 'thanks.html', context)
 
@@ -126,6 +125,7 @@ class RenewView(LoginRequiredMixin, MyUpdateView):
             obj.first_name = u.first_name
             obj.last_name = u.last_name
             obj.email_address = u.email
+            obj.login_token = None # renewing members won't need this
         return obj
 
     def get_context_data(self, **kwargs):
diff --git a/src/memberdb/views.py b/src/memberdb/views.py
index b0abaa51692339999d16ffbe646576cd3a0f8934..a1c067039bec3e19244e17bb18f195a29961d801 100644
--- a/src/memberdb/views.py
+++ b/src/memberdb/views.py
@@ -10,7 +10,7 @@ from django.views.generic.edit import UpdateView
 from django.contrib.auth.mixins import AccessMixin
 from django.utils import timezone
 
-from .models import Member, IncAssocMember, Membership
+from .models import Member, IncAssocMember, Membership, MEMBERSHIP_TYPES, TokenConfirmation
 from .forms import MemberHomeForm
 
 class MemberMiddleware:
@@ -48,10 +48,6 @@ class MemberMiddleware:
             request.member = Member.objects.get(id=request.session['member_id'])
 
         response = self.get_response(request)
-
-        # Code to be executed for each request/response after
-        # the view is called.
-
         return response
 
 class MemberAccessMixin(AccessMixin):
@@ -66,7 +62,6 @@ Can update and create models.
 Also passes the request object to the form via its kwargs.
 """
 class MyUpdateView(UpdateView):
-    can_create = True
     object = None
 
     def get_object(self):
@@ -93,12 +88,27 @@ class MemberHomeView(MemberAccessMixin, MyUpdateView):
     def get_object(self):
         return self.request.member
 
+    def get_membership_context(self, ms):
+        """ gets the per-membership-record context data """
+        return {
+            'id': ms.id,
+            'type': MEMBERSHIP_TYPES[ms.membership_type]['desc'],
+            'submitted': ms.date_submitted.strftime('%Y-%m-%d %H:%M'),
+            'paid': ms.date_paid.strftime('%Y-%m-%d %H:%M') if ms.date_paid is not None else None,
+            'approved': ms.date_approved.strftime('%Y-%m-%d %H:%M') if ms.approved else None,
+            'is_approved': ms.approved,
+        }
+
     def get_context_data(self):
         d = super().get_context_data()
         m = self.get_object()
-        d.update({
-            'memberships': m.memberships.all() if m is not None else None,
-        })
+
+        if m is not None:
+            # get a list of all the membership records associated with this member
+            ms_list = [ self.get_membership_context(ms) for ms in m.memberships.all() ]
+            d.update({
+                'memberships': ms_list,
+            })
         return d
 
     def form_valid(self, form):
@@ -111,15 +121,36 @@ class MemberHomeView(MemberAccessMixin, MyUpdateView):
 class MemberTokenView(View):
     """ allow a user to login using a unique (secure) member token """
     def get(self, request, **kwargs):
-        if not ('member_token' in kwargs and 'username' in kwargs) or request.user.is_authenticated:
-            raise Http404()
+        if not request.user.is_authenticated:
+            # look up the member using exact match for token and username, and registered < 7 days ago
+            week_ago = timezone.now() - timedelta(days=7)
+
+            try:
+                member = Member.objects.get(
+                    login_token=kwargs['member_token'],
+                    username=kwargs['username'],
+                    created__gte=week_ago
+                )
+            except Member.DoesNotExist:
+                raise Http404()
 
-        # look up the member using exact match for token and username, and registered < 7 days ago
-        week_ago = timezone.now() - timedelta(days=7)
+        request.session['member_id'] = member.id
+        return HttpResponseRedirect(reverse('memberdb:home'))
 
-        member = Member.objects.get(login_token=kwargs['member_token'], username=kwargs['username'], created__gte=week_ago)
-        if member is None:
-            raise Http404()
+class EmailConfirmView(View):
+    """ process email confirmations """
 
-        request.session['member_id'] = member.id
+    def get(self, request, **kwargs):
+        week_ago = timezone.now() - timedelta(days=7)
+        try:
+            c = TokenConfirmation.objects.get(
+                id = kwargs['pk'],
+                confirm_token = kwargs['token'],
+                created__gte = week_ago
+            )
+            c.mark_confirmed()
+        except:
+            pass
+        messages.success(request, "Your email address has been confirmed.")
         return HttpResponseRedirect(reverse('memberdb:home'))
+
diff --git a/src/static/memberdb.css b/src/static/memberdb.css
index 74752c0452c888d7de41dae8c9f5102bac1806e1..004be23a6dae2550e8c7fd41ee4fd8d666860070 100644
--- a/src/static/memberdb.css
+++ b/src/static/memberdb.css
@@ -130,3 +130,8 @@ nav {
 .navtab:last-child {
     border-right: 1.5px solid #555;
 }
+
+.member-details, .membership-details {
+    width: 100%;
+    text-align: left;
+}
diff --git a/src/static/shared.css b/src/static/shared.css
index e1a893818bd35010dfb11b1be756e8c05a7ac7c9..dc9e6ceb24e1fcbb0c03e83f3fa8938e690ae982 100644
--- a/src/static/shared.css
+++ b/src/static/shared.css
@@ -126,6 +126,7 @@ ul.messagelist li.error {
 
 a.button {
     padding: 4px 5px;
+    display: inline-block;
 }
 
 .button:active, input[type=submit]:active, input[type=button]:active,
@@ -161,3 +162,57 @@ input[type=button][disabled].default {
     font-size: 12px;
     color: #999;
 }
+
+/* TABLES */
+
+table {
+    border-collapse: collapse;
+    border-color: #ccc;
+}
+
+td, th {
+    font-size: 13px;
+    line-height: 16px;
+    border-bottom: 1px solid #eee;
+    vertical-align: top;
+    padding: 8px;
+    /*font-family: "Roboto", "Lucida Grande", Verdana, Arial, sans-serif;*/
+}
+
+th {
+    font-weight: 600;
+    text-align: left;
+}
+
+thead th,
+tfoot td {
+    color: #666;
+    padding: 5px 10px;
+    font-size: 11px;
+    background: #fff;
+    border: none;
+    border-top: 1px solid #eee;
+    border-bottom: 1px solid #eee;
+}
+
+tfoot td {
+    border-bottom: none;
+    border-top: 1px solid #eee;
+}
+
+thead th.required {
+    color: #000;
+}
+
+tr.alt {
+    background: #f6f6f6;
+}
+
+.row1 {
+    background: rgba(255, 255, 255, 0.7);
+}
+
+.row2 {
+    background: rgba(230, 230, 230, 0.7);
+}
+
diff --git a/src/templates/admin/memberdb/membership_actions.html b/src/templates/admin/memberdb/membership_actions.html
index 51019cba9f78557b3aa788e411a7b4bff49a47e4..6073fe9412c12194dc85e258f034a478713d78a6 100644
--- a/src/templates/admin/memberdb/membership_actions.html
+++ b/src/templates/admin/memberdb/membership_actions.html
@@ -1,7 +1,7 @@
-{% load static %}
+{% load static %}{# this template is used to generate the member action buttons, see memberdb/admin.py #}
 <div class="member-actions">
-    <a class="button" href="{{ member_url }}">Edit Member</a>&nbsp;
+    <a class="button" href="{{ member_url }}">Edit</a>&nbsp;
     {% if not ms.approved %}
     <a class="button" href="{{ member_approve }}">Approve</a>&nbsp;
     {% endif %}
-</div>
\ No newline at end of file
+</div>
diff --git a/src/templates/admin/memberdb/membership_summary.html b/src/templates/admin/memberdb/membership_summary.html
index 3f8de8d1a284481567c0b0015e66a034b5bada86..702b76935eb18c7fe979b0d2e2940b37b63a6ee4 100644
--- a/src/templates/admin/memberdb/membership_summary.html
+++ b/src/templates/admin/memberdb/membership_summary.html
@@ -1,39 +1,6 @@
-{% load static %}
-{% block member-summary %}
-<table class="ms-summary">
-    <tr class="{% cycle 'row1' 'row2' as rcl %}">
-        <th>Real name</th>
-        <td><b>{{ member.first_name }} {{ member.last_name }}</b></td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Username &amp; display name</th>
-        <td><b>{{ member.username }}</b> ({{ member.display_name }})</td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Email</th>
-        <td>
-        {% if member.email_address %}
-            <a href="mailto:{{ member.email_address }}">{{ member.email_address }}</a>
-        {% else %}
-            <i>not provided</i>
-        {% endif %}
-        </td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Phone number</th>
-        <td>{% if member.phone_number %}{{ member.phone_number }}{% else %}<i>not provided</i>{% endif %}</td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Is student</th>
-        <td>{% if member.is_student %}<img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">{% else %}<img src="{% static 'admin/img/icon-no.svg' %}" alt="no">{% endif %}</td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Is UWA Guild</th>
-        <td>{% if member.is_guild %}<img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">{% else %}<img src="{% static 'admin/img/icon-no.svg' %}" alt="no">{% endif %}</td>
-    </tr>
-    <tr class="{% cycle rcl %}">
-        <th>Student / License no.</th>
-        <td>{% if member.id_number %}{{ member.id_number }}{% else %}<i>not provided</i>{% endif %}</td>
-    </tr>
-</table>
-{% endblock %}
\ No newline at end of file
+{# this template is rendered and displayed as the contents of the "membership info" column in the admin pages #}
+{% extends "membership_summary.html" %}
+
+{% block header1 %}{% endblock %}
+
+
diff --git a/src/templates/base_form.html b/src/templates/base_form.html
index 76d12e8e7fcc45f68a07a051a613a85158f2a911..a979ae5f92ea3add22d12650b19a3d8173adfe06 100644
--- a/src/templates/base_form.html
+++ b/src/templates/base_form.html
@@ -37,6 +37,7 @@
             {% endif %}
         </div>
         {% endfor %}
+        {% block postform %}{% endblock %}
         <div class="submit-row">
             <input type="submit" class="default" value="{% block action_text %}Register{% endblock %}">
         </div>
diff --git a/src/templates/home.html b/src/templates/home.html
index 5c86bb993b52e1b49c6c76ac589948d4c9041998..4961defc30abaa76fb9db16f39810d17687aff52 100644
--- a/src/templates/home.html
+++ b/src/templates/home.html
@@ -1,34 +1,92 @@
 {% extends "base_form.html" %}
+{% load static %}
 {% block title %}UCC Member Home{% endblock %}
 {% block content_title %}
     <h1>Member home</h1>
-    <h3>Welcome, {{ request.member.first_name }} {{ request.member.last_name }} ({{ request.member.username }})</h3>
+    {% if request.member %}
+    <h3>Welcome, {{ request.member.first_name }} {{ request.member.last_name }} (<code>{{ request.member.username }}</code>)</h3>
+    {% else %}
+    <h3>Welcome, {{ request.user.first_name }} {{ request.user.last_name }} (<code>{{ request.user.username }}</code>)</h3>
+    {% endif %}
 {% endblock %}
 
 {% block tips %}
 {% if not request.member %}
-{% if request.user.is_authenticated %}
-<b>You have no member record associated with this account.</b><br>
-Please <a href="{% url 'memberdb:renew' %}">renew your membership</a> to get started.
+    {% if request.user.is_authenticated %}
+    <b>You have no member record associated with this account.</b><br>
+    Please <a href="{% url 'memberdb:renew' %}">renew your membership</a> to get started.
+    {% else %}
+    <b>Something went wrong and your membership details could not be retrieved.</b> Please try <a href="{% url 'memberdb:login' %}">logging in</a>.
+    {% endif %}
 {% else %}
-<b>Something went wrong and your membership details could not be retrieved.</b> Please try <a href="{% url 'memberdb:login' %}">logging in</a>.
-{% endif %}
-{% else %}
-You can see and modify some of your membership and account details below.
+    You can see and modify some of your membership and account details below.
 {% endif %}
 {% endblock %}
 
 {% block extra_preform %}
-<div class="form-row readonly">
-    <label for="id_username">Username:</label>
-    <span class="text" id="id_username">{{ object.username }}</span>
+<div class="form-row">
+    {% include 'membership_summary.html' %}
+</div>
+<div class="form-row">
+    <h4>Membership renewals on record</h4>
+    <!-- stuff from the membership record itself -->
+    {% if memberships %}
+    <table class="membership-details">
+        <tr class="{% cycle 'row1' 'row2' as rcl %}">
+            <th>Membership type</th>
+            <th>Submitted</th>
+            <th>Paid</th>
+            <th>Approved</th>
+            <th>Actions</th>
+        </tr>
+        {% for ms in memberships %}
+        <tr class="{% cycle rcl %}">
+            <td>
+                {{ ms.type }}
+            </td>
+            <td>
+                {{ ms.submitted }}
+            </td>
+            <td>
+                {% if ms.paid %}
+                <img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">&nbsp; {{ ms.paid }}
+                {% else %}
+                <img src="{% static 'admin/img/icon-no.svg' %}" alt="no">&nbsp; Not paid yet
+                {% endif %}
+            </td>
+            <td>
+                {% if ms.approved and ms.is_approved %}
+                <img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">&nbsp; {{ ms.approved }}
+                {% elif ms.approved and not ms.is_approved %}
+                <img src="{% static 'admin/img/icon-no.svg' %}" alt="no">&nbsp; Rejected: {{ ms.approved }}
+                {% else %}
+                <img src="{% static 'admin/img/icon-unknown.svg' %}" alt="?">&nbsp; Not approved yet
+                {% endif %}
+            </td>
+            <td>
+                <!-- membership actions -->
+                {% if not ms.paid %}<a class="button" href="{% url 'squarepay:pay_membership' ms.id %}">Pay now</a>{% endif %}
+            </td>
+        </tr>
+        {% endfor %}
+    </table>
+    {% else %}
+    No membership renewal records for your account exist yet. Please <a href="{% url 'memberdb:renew' %}">renew your membership</a> to get started.
+    {% endif %}
 </div>
+<br>
 {% endblock %}
 
 {% block form %}
 {% if object %} {{ block.super }} {% endif %}
 {% endblock %}
 
+{% block postform %}
+<div class="form-row">
+<p class="help">To update your other membership details, please talk to a door or committee member.</p>
+</div>
+{% endblock %}
+
 {% block action_url %}{% url 'memberdb:home' %}{% endblock %}
 
 {% block action_text %}Update details{% endblock %}
diff --git a/src/templates/membership_summary.html b/src/templates/membership_summary.html
new file mode 100644
index 0000000000000000000000000000000000000000..aeffa35b3f30715546aab9fd453ebb67de50e41e
--- /dev/null
+++ b/src/templates/membership_summary.html
@@ -0,0 +1,55 @@
+{# this template is used by the admin membership renewal page and member homepage #}
+{% load static %}
+{% block header1 %}
+<h4>Current member details</h4>
+{% endblock %}
+{% block member_details %}
+<!-- try to display only the details which aren't editable on member home page -->
+<table class="member-details">
+    {% block name %}
+    <tr class="{% cycle 'row1' 'row2' as rcl %}">
+        <th>Real name</th>
+        <td><b>{{ member.first_name }} {{ member.last_name }}</b></td>
+    </tr>
+    <tr class="{% cycle rcl %}">
+        <th>Username &amp; display name</th>
+        <td><b>{{ member.username }}</b> ({{ member.display_name }})</td>
+    </tr>
+    {% endblock %}
+
+    {% block email %}
+    <tr class="{% cycle rcl %}">
+        <th>Email</th>
+        <td>
+        {% if member.email_address %}
+            <a href="mailto:{{ member.email_address }}">{{ member.email_address }}</a>
+        {% else %}
+            <i>not provided</i>
+        {% endif %}
+        </td>
+    </tr>
+    {% endblock %}
+
+    {% block phone %}
+    <tr class="{% cycle rcl %}">
+        <th>Phone number</th>
+        <td>{% if member.phone_number %}{{ member.phone_number }}{% else %}<i>not provided</i>{% endif %}</td>
+    </tr>
+    {% endblock %}
+
+    {% block student %}
+    <tr class="{% cycle rcl %}">
+        <th>Is student</th>
+        <td>{% if member.is_student %}<img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">{% else %}<img src="{% static 'admin/img/icon-no.svg' %}" alt="no">{% endif %}</td>
+    </tr>
+    <tr class="{% cycle rcl %}">
+        <th>Is UWA Guild</th>
+        <td>{% if member.is_guild %}<img src="{% static 'admin/img/icon-yes.svg' %}" alt="yes">{% else %}<img src="{% static 'admin/img/icon-no.svg' %}" alt="no">{% endif %}</td>
+    </tr>
+    <tr class="{% cycle rcl %}">
+        <th>Student email / Drivers license</th>
+        <td>{% if member.id_number %}{{ member.id_number }}{% else %}<i>not provided</i>{% endif %}</td>
+    </tr>
+    {% endblock %}
+</table>
+{% endblock %}