diff --git a/requirements.txt b/requirements.txt
index 8ee0523154b9e8a7dbfef7c33680d5aebdd49ff6..a6da722f9a2f5e8bf4bf339ec2ab265ba73badaf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
 django-bootstrap5~=24.2
-django-gravatar2~=1.4.4
\ No newline at end of file
+django-gravatar2~=1.4.4
+Django~=5.0.7
\ No newline at end of file
diff --git a/tcalendar/urls.py b/tcalendar/urls.py
index dbc247046edf635fdb9241cc3c75ffd002b9a66e..945c2ebd8faf6e37fb4ef577669bcbbbe15bc6ff 100644
--- a/tcalendar/urls.py
+++ b/tcalendar/urls.py
@@ -16,9 +16,11 @@ Including another URLconf
 """
 from django.contrib import admin
 from django.urls import path, include
+from django.views.generic import TemplateView
 
 urlpatterns = [
     path('admin/', admin.site.urls),
     path("accounts/", include("django.contrib.auth.urls")),
+    path("accounts/profile/", TemplateView.as_view(template_name="registration/profile.html"), name="profile"),
     path('', include("tcal.urls")),
 ]
diff --git a/templates/registration/logged_out.html b/templates/registration/logged_out.html
new file mode 100644
index 0000000000000000000000000000000000000000..c160b123fd7c495081033f54ac29522bbaedfec1
--- /dev/null
+++ b/templates/registration/logged_out.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block title %}Logged Out{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Message
+        </div>
+        <div class="card-body">
+            You have been logged out. To log back in, <a href="{% url "login" %}">click here</a>.
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/login.html b/templates/registration/login.html
new file mode 100644
index 0000000000000000000000000000000000000000..24d38a6ea88ffe426b51fc808d80cd0dfd410d8c
--- /dev/null
+++ b/templates/registration/login.html
@@ -0,0 +1,59 @@
+{% extends "base.html" %}
+
+{% block title %}Login{% endblock %}
+
+{% block content %}
+    <br>
+    {% if form.errors and not form.non_field_errors %}
+        <div class="alert alert-danger" role="alert">
+            Please correct the error(s) below.
+        </div>
+    {% endif %}
+    {% if form.non_field_errors %}
+        {% for error in form.non_field_errors %}
+            <div class="alert alert-danger" role="alert">
+                {{ error }}
+            </div>
+        {% endfor %}
+    {% endif %}
+    {% if user.is_authenticated %}
+        <div class="alert alert-danger" role="alert">
+            You are authenticated as {{ username }}, but are not authorized to
+            access this page. Would you like to login to a different account?
+        </div>
+    {% endif %}
+    <div class="card">
+        <div class="card-header">
+            Login
+        </div>
+        <div class="card-body">
+            {% if form.errors and not form.non_field_errors %}
+
+            {% endif %}
+            <form method="post">
+                {% csrf_token %}
+                <div class="mb-3">
+                    {{ form.username.errors }}
+                    <label for="id_username" class="form-label">Username</label>
+                    <input type="text" class="form-control" id="id_username" name="username">
+                </div>
+                <div class="mb-3">
+                    {{ form.password.errors }}
+                    <label for="id_password" class="form-label">Password</label>
+                    <input type="password" class="form-control" id="id_password" name="password">
+                </div>
+                <button type="submit" class="btn btn-primary">Submit</button>
+            </form>
+        </div>
+    </div>
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Forgotten Password
+        </div>
+        <div class="card-body">
+            <p>If you have forgotten your password, please click <a href="{% url "password_reset" %}">here</a>.</p>
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_change_done.html b/templates/registration/password_change_done.html
new file mode 100644
index 0000000000000000000000000000000000000000..3e6ad91a121ea4374ea56b62fcdaf7d5a1bada18
--- /dev/null
+++ b/templates/registration/password_change_done.html
@@ -0,0 +1,21 @@
+{% extends "base.html" %}
+
+{% block title %}Logged Out{% endblock %}
+
+{% block navbar_items %}
+    {{ block.super }}
+    <a class="nav-link active" aria-current="page" href="{% url "profile" %}">Profile</a>
+{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Success
+        </div>
+        <div class="card-body">
+            Your password has been changed.
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_change_form.html b/templates/registration/password_change_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..d20d3c7d4b5a32d9bada16be1062c593f5376179
--- /dev/null
+++ b/templates/registration/password_change_form.html
@@ -0,0 +1,49 @@
+{% extends "base.html" %}
+
+{% block title %}Change Password{% endblock %}
+
+{% block navbar_items %}
+    {{ block.super }}
+    <a class="nav-link active" aria-current="page" href="{% url "profile" %}">Profile</a>
+{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Change Password
+        </div>
+        <div class="card-body">
+            {% if form.errors %}
+                <p class="errornote"><strong>
+                    {% if form.errors.items|length > 1 %}
+                        Please correct the errors below.
+                    {% else %}
+                        Please correct the error below.
+                    {% endif %}
+                </strong></p>
+            {% endif %}
+            <p class="lead">Please enter your old password, for security’s sake, and then enter your new password twice so we can verify you typed it in correctly.</p>
+            <form method="post">
+                {% csrf_token %}
+                <div class="mb-3">
+                    {{ form.old_password.errors }}
+                    <label for="id_old_password" class="form-label">Old Password:</label>
+                    <input type="password" class="form-control" id="id_old_password" name="old_password">
+                </div>
+                <div class="mb-3">
+                    {{ form.new_password1.errors }}
+                    <label for="id_new_password1" class="form-label">New Password:</label>
+                    <input type="password" class="form-control" id="id_new_password1" name="new_password1">
+                </div>
+                <div class="mb-3">
+                    {{ form.new_password2.errors }}
+                    <label for="id_new_password2" class="form-label">New Password (repeat):</label>
+                    <input type="password" class="form-control" id="id_new_password2" name="new_password2">
+                </div>
+                <button type="submit" class="btn btn-primary">Change my password</button>
+            </form>
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_complete.html b/templates/registration/password_reset_complete.html
new file mode 100644
index 0000000000000000000000000000000000000000..29468b3f5926aac63b307b5e3c8ba18beb665dab
--- /dev/null
+++ b/templates/registration/password_reset_complete.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% block title %}Password Reset Complete{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Success
+        </div>
+        <div class="card-body">
+            <p>Your password has been set. You may go ahead and log in now.</p>
+            <p><a class="btn btn-primary" href="{{ login_url }}">Log in</a></p>
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_confirm.html b/templates/registration/password_reset_confirm.html
new file mode 100644
index 0000000000000000000000000000000000000000..43d00917fe9c8310283e25c91e2aec5e0d7b6640
--- /dev/null
+++ b/templates/registration/password_reset_confirm.html
@@ -0,0 +1,34 @@
+{% extends "base.html" %}
+
+{% block title %}Password Reset{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Password Reset Confirmation
+        </div>
+        <div class="card-body">
+            {% if validlink %}
+                <p class="lead">Please enter your new password twice, so we can verify you typed it in correctly.</p>
+                <form method="post">
+                    {% csrf_token %}
+                    <div class="mb-3">
+                        {{ form.new_password1.errors }}
+                        <label for="id_new_password1" class="form-label">New Password</label>
+                        <input type="password" class="form-control" id="id_new_password1" name="new_password1">
+                    </div>
+                    <div class="mb-3">
+                        {{ form.new_password2.errors }}
+                        <label for="id_new_password2" class="form-label">Confirm Password</label>
+                        <input type="password" class="form-control" id="id_new_password2" name="new_password2">
+                    </div>
+                    <button type="submit" class="btn btn-primary">Change password</button>
+                </form>
+            {% else %}
+                <p>The password reset link was invalid, possibly because it has already been used.  Please request a new password reset.</p>
+            {% endif %}
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_done.html b/templates/registration/password_reset_done.html
new file mode 100644
index 0000000000000000000000000000000000000000..9d5df1246ca9523e59849f4ea0a2623691111889
--- /dev/null
+++ b/templates/registration/password_reset_done.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% block title %}Logged Out{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Success
+        </div>
+        <div class="card-body">
+            We’ve emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.<br>
+            If you don’t receive an email, please make sure you’ve entered the address you registered with, and check your spam folder.
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_email.html b/templates/registration/password_reset_email.html
new file mode 100644
index 0000000000000000000000000000000000000000..48a87de0156679fe1d3a997fad2115d9efa29e7f
--- /dev/null
+++ b/templates/registration/password_reset_email.html
@@ -0,0 +1,15 @@
+{% extends "email_base.html" %}
+
+{% block content %}
+    You're receiving this email because you requested a password reset for your user account at {{ site_name }}.
+
+    Please go to the following page and choose a new password:
+    {% block reset_link %}
+    {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
+    {% endblock %}
+    Your username, in case you’ve forgotten: {{ user.get_username }}
+
+    Thanks for using our site!
+
+    The {{ site_name }} team
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_form.html b/templates/registration/password_reset_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..772ee8189feba058f9bef595e8134845b3b7125a
--- /dev/null
+++ b/templates/registration/password_reset_form.html
@@ -0,0 +1,25 @@
+{% extends "base.html" %}
+
+{% block title %}Password Reset{% endblock %}
+
+{% block content %}
+    <br>
+    <div class="card">
+        <div class="card-header">
+            Password Reset
+        </div>
+        <div class="card-body">
+            <p class="lead">Forgotten your password? Enter your email address below, and we’ll email instructions for setting a new one.</p>
+            <form method="post">
+                {% csrf_token %}
+                <div class="mb-3">
+                    {{ form.email.errors }}
+                    <label for="id_email" class="form-label">Email</label>
+                    <input type="email" class="form-control" id="id_email" name="email" autocomplete="email">
+                </div>
+                <button type="submit" class="btn btn-primary">Submit</button>
+            </form>
+        </div>
+    </div>
+
+{% endblock %}
\ No newline at end of file
diff --git a/templates/registration/password_reset_subject.txt b/templates/registration/password_reset_subject.txt
new file mode 100644
index 0000000000000000000000000000000000000000..61c61982d4f066dd7625ca098f7b4fb2a631a991
--- /dev/null
+++ b/templates/registration/password_reset_subject.txt
@@ -0,0 +1,3 @@
+{% autoescape off %}
+Password reset on {{ site_name }}
+{% endautoescape %}
\ No newline at end of file
diff --git a/templates/registration/profile.html b/templates/registration/profile.html
new file mode 100644
index 0000000000000000000000000000000000000000..d5b22179eb219a5f22c74bd24edf2ba5d65e530f
--- /dev/null
+++ b/templates/registration/profile.html
@@ -0,0 +1,40 @@
+{% extends "base.html" %}
+{% load gravatar %}
+
+{% block title %}Profile{% endblock %}
+
+{% block navbar_items %}
+    {{ block.super }}
+    <li class="nav-item">
+        <a class="nav-link active" aria-current="page" href="{% url "profile" %}">Profile</a>
+    </li>
+{% endblock %}
+
+{% block content %}
+    <div class="card" id="card-profile">
+        <div class="card-header">
+            Profile
+        </div>
+        <div class="card-body">
+            <div class="row">
+                <div class="col-md-4">
+                    <img src="{% gravatar_url user.email 150 %}" class="rounded-circle mx-auto d-block" alt="Profile image" width="150" height="150">
+                </div>
+                <div class="col-md-8">
+                    {% if user.first_name or user.last_name %}
+                        <h3>{{ user.first_name }} {{ user.last_name }}</h3>
+                    {% else %}
+                        <h3>{{ user.username }}</h3>
+                    {% endif %}
+                    <br>
+                    <p><b>Username:</b> {{ user.username }}</p>
+                    <p><b>Primary Email:</b> {{ user.email }}</p>
+                    <p><b>Account Created:</b> {{ user.date_joined }}</p>
+                    <br>
+                    <p><a class="btn btn-primary" href="{% url "password_change" %}">Change Password</a></p>
+                </div>
+            </div>
+        </div>
+    </div>
+    <br>
+{% endblock %}