diff --git a/panel/nix/tests.nix b/panel/nix/tests.nix
index eaa90681..a8259384 100644
--- a/panel/nix/tests.nix
+++ b/panel/nix/tests.nix
@@ -26,7 +26,7 @@ lib.mapAttrs (name: test: pkgs.testers.runNixOSTest (test // { inherit name; }))
     # run all application-level tests managed by Django
     # https://docs.djangoproject.com/en/5.0/topics/testing/overview/
     testScript = ''
-      server.succeed("manage test")
+      server.succeed("manage test ${name}")
     '';
   };
   admin = {
diff --git a/panel/src/panel/templates/base.html b/panel/src/panel/templates/base.html
index 7f8b2e18..aa29745a 100644
--- a/panel/src/panel/templates/base.html
+++ b/panel/src/panel/templates/base.html
@@ -30,7 +30,7 @@
           {% load custom_tags %}
           <li>
           {% if user.is_authenticated %}
-            Welcome, {{ user.username }}! <a id="logout" href="{% auth_url 'logout' %}">Logout</a>
+            Welcome, <a href="{% url 'account_detail' %}">{{ user.username }}</a>! <a id="logout" href="{% auth_url 'logout' %}">Logout</a>
           {% else %}
             <a id="login" href="{% auth_url 'login' %}">Login</a>
           {% endif %}
diff --git a/panel/src/panel/tests/__init__.py b/panel/src/panel/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/panel/src/panel/tests/test_user_stories.py b/panel/src/panel/tests/test_user_stories.py
new file mode 100644
index 00000000..8f45ae4c
--- /dev/null
+++ b/panel/src/panel/tests/test_user_stories.py
@@ -0,0 +1,104 @@
+from django.test import TestCase
+from django.urls import reverse
+from django.contrib.auth.models import User
+from django.template import Template, Context
+from urllib.parse import unquote
+
+class Login(TestCase):
+    def setUp(self):
+        self.username = 'testuser'
+        self.password = 'securepassword123'
+        self.user = User.objects.create_user(
+            username=self.username,
+            email='test@example.com',
+            password=self.password
+        )
+
+        self.login = reverse('login')
+        self.logout = reverse('logout')
+        self.required_login = reverse('account_detail')
+        self.optional_login = reverse('service_list')
+
+    def test_optional_login_redirects_back_to_original_page(self):
+        # go to a view where authentication is optional
+        response = self.client.get(self.optional_login)
+        self.assertEqual(response.status_code, 200)
+        self.assertFalse(response.context['user'].is_authenticated)
+
+        # check that the expected login URL is in the response
+        context = response.context[0]
+        template = Template("{% load custom_tags %}{% auth_url 'login' %}")
+        login_url = template.render(context)
+        self.assertIn(login_url, response.content.decode('utf-8'))
+
+        # log in
+        response = self.client.get(login_url)
+        self.assertEqual(response.status_code, 200)
+
+        login_data = {
+            'username': self.username,
+            'password': self.password,
+        }
+        response = self.client.post(login_url, login_data, follow=True)
+
+        # check that we're back at the desired view and authenticated
+        self.assertEqual(response.status_code, 200)
+        self.assertTrue(response.context['user'].is_authenticated)
+        location, status = response.redirect_chain[-1]
+        self.assertEqual(location, self.optional_login)
+
+        # check that the expected logout URL is present
+        context = response.context[0]
+        template = Template("{% load custom_tags %}{% auth_url 'logout' %}")
+        logout_url = template.render(context)
+        self.assertIn(logout_url, response.content.decode('utf-8'))
+
+        # log out again
+        response = self.client.get(logout_url, follow=True)
+
+        # check that we're back at the view and logged out
+        self.assertEqual(response.status_code, 200)
+        location, status = response.redirect_chain[-1]
+        self.assertEqual(location, self.optional_login)
+        self.assertFalse(response.context['user'].is_authenticated)
+
+    def test_required_login_redirects_back_login(self):
+        # go to a view that requires authentication
+        response = self.client.get(self.required_login)
+
+        # check that we're redirected to the login view
+        self.assertEqual(response.status_code, 302)
+        redirect = response.url
+        self.assertTrue(redirect.startswith(self.login))
+
+        # log in
+        response = self.client.get(redirect)
+        self.assertEqual(response.status_code, 200)
+        login_data = {
+            'username': self.username,
+            'password': self.password,
+        }
+        response = self.client.post(redirect, login_data, follow=True)
+
+        # check that we reached the desired view, authenticated
+        self.assertEqual(response.status_code, 200)
+        location, status = response.redirect_chain[-1]
+        self.assertEqual(location, self.required_login)
+        self.assertTrue(response.context['user'].is_authenticated)
+
+        # check that the expected logout URL is present
+        context = response.context[0]
+        template = Template("{% load custom_tags %}{% auth_url 'logout' %}")
+        logout_url = template.render(context)
+        self.assertIn(logout_url, response.content.decode('utf-8'))
+
+        # log out
+        response = self.client.get(logout_url, follow=True)
+
+        # check that we're at the expected location, logged out
+        self.assertEqual(response.status_code, 200)
+        template = Template("{% load custom_tags %}{% auth_url 'login' %}")
+        login_url = template.render(context)
+        location, status = response.redirect_chain[-1]
+        self.assertEqual(location, unquote(login_url))
+        self.assertFalse(response.context['user'].is_authenticated)