diff --git a/django_project/myapp/forms.py b/django_project/myapp/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..16718dce960dc395262f958b88cebbd24d438248
--- /dev/null
+++ b/django_project/myapp/forms.py
@@ -0,0 +1,25 @@
+from django import forms
+from django.contrib.auth import authenticate
+
+class EmailLoginForm(forms.Form):
+    email = forms.EmailField(label="Email")
+    password = forms.CharField(widget=forms.PasswordInput)
+
+    def clean(self):
+        cleaned_data = super().clean()
+        email = cleaned_data.get("email")
+        password = cleaned_data.get("password")
+
+        from django.contrib.auth import get_user_model
+        User = get_user_model()
+
+        try:
+            user = User.objects.get(email=email)
+        except User.DoesNotExist:
+            raise forms.ValidationError("No user with that email.")
+
+        self.user = authenticate(username=user.username, password=password)
+        if self.user is None:
+            raise forms.ValidationError("Invalid password.")
+
+        return cleaned_data
diff --git a/django_project/myapp/templates/myapp/group_create.html b/django_project/myapp/templates/myapp/group_create.html
index c55d83fb084668692bf576d55df4f2698e3aa2b2..8ce3d22f8120261ef2dd8a841bd570856060623f 100644
--- a/django_project/myapp/templates/myapp/group_create.html
+++ b/django_project/myapp/templates/myapp/group_create.html
@@ -14,6 +14,9 @@
         <label for="id_name">Group Name:</label>
         <input type="text" name="name" id="id_name" required>
         <br><br>
+        <label>Tags (comma-separated):</label>
+        <input type="text" name="tags"><br>
+        
         <button type="submit">Create Group</button>
     </form>
 
diff --git a/django_project/myapp/templates/myapp/group_detail.html b/django_project/myapp/templates/myapp/group_detail.html
index d34906382b2dfe0a6b1634b862d46e1bbacdb291..8f24e08eecc86b3822385ef841305d155d46dd80 100644
--- a/django_project/myapp/templates/myapp/group_detail.html
+++ b/django_project/myapp/templates/myapp/group_detail.html
@@ -3,23 +3,52 @@
 {% block title %}Group Details{% endblock %}
 
 {% block content %}
-    <h1>Group Details</h1>
-    {% if error %}
-        <p style="color: red;">{{ error }}</p>
+<h1>Group Details</h1>
+
+{% if error %}
+    <p style="color: red;">{{ error }}</p>
+{% elif group %}
+    <p><strong>Group Name:</strong> {{ group.name }}</p>
+    <p><strong>Group ID:</strong> {{ group.id }}</p>
+    <p><strong>Member Count:</strong> {{ group.member_count }}</p>
+
+    {% if group.tags %}
+        <p><strong>Tags:</strong>
+            {% for tag in group.tags %}
+                <span style="display: inline-block; background-color: #eee; padding: 4px 8px; margin-right: 5px; border-radius: 4px;">
+                    {{ tag }}
+                </span>
+            {% endfor %}
+        </p>
     {% else %}
-        <p><strong>Group Name:</strong> {{ group.name }}</p>
-        <p><strong>Group ID:</strong> {{ group.id }}</p>
-        <p><strong>Member Count:</strong> {{ group.member_count }}</p>
-        {% if request.user in group.members.all %}
-        <p>You’re already a member of this group.</p>
+        <p><strong>Tags:</strong> <em>No tags assigned.</em></p>
+    {% endif %}
+
+    {% if user_id %}
+        {% if is_member %}
+            <p>You’re already a member of this group.</p>
         {% else %}
-        <form method="post">
-            {% csrf_token %}
-            <input type="hidden" name="user_id" value="{{ request.user.id }}">
-            <button type="submit">Join Group</button>
-        </form>
+            <form method="post">
+                {% csrf_token %}
+                <input type="hidden" name="user_id" value="{{ user_id }}">
+                <button type="submit">Join Group</button>
+            </form>
+        {% endif %}
+    {% else %}
+        <p><a href="{% url 'login' %}">Log in</a> to join this group.</p>
     {% endif %}
+
+    <h2>Members</h2>
+    {% if members %}
+        <ul>
+            {% for member in members %}
+                <li>{{ member.name }} ({{ member.email }})</li>
+            {% endfor %}
+        </ul>
+    {% else %}
+        <p>No members yet.</p>
     {% endif %}
-    <p><a href="{% url 'group_list' %}">Back to Groups</a></p>
-</body>
+{% endif %}
+
+<p><a href="{% url 'group_list' %}">Back to Groups</a></p>
 {% endblock %}
diff --git a/django_project/myapp/templates/myapp/login.html b/django_project/myapp/templates/myapp/login.html
index dd14de3d34faeaeac9ebd4eead55eaf033955ab5..ce831fde2cfed5f7c676a77f7caa8633749fca50 100644
--- a/django_project/myapp/templates/myapp/login.html
+++ b/django_project/myapp/templates/myapp/login.html
@@ -56,19 +56,21 @@
         <div class="left">
             <div>
                 <h1>Login</h1>
-                {% if error %}
-                  <p class="error">{{ error }}</p>
+                {% if form.errors %}
+                  <p class="error">Invalid login. Please try again.</p>
                 {% endif %}
                 <form method="post">
                     {% csrf_token %}
-                    <label for="id_email">Email:</label>
-                    <input type="email" name="email" id="id_email" required><br>
                     
+                    <label for="id_email">Email:</label>
+                    <input type="email" name="email" id="id_email" value="{{ form.email.value|default_if_none:'' }}" required><br>
+    
                     <label for="id_password">Password:</label>
                     <input type="password" name="password" id="id_password" required><br>
-                    
+    
                     <button type="submit">Login</button>
                 </form>
+    
                 <p>
                     Don't have an account?
                     <a href="{% url 'register' %}">Register here</a>.
@@ -79,7 +81,7 @@
             <h1>UniHub</h1>
             <p>Where university happens.</p>
         </div>
-    </div>
+    </div>    
 </body>
 </html>
 
diff --git a/django_project/myapp/views/events_views.py b/django_project/myapp/views/events_views.py
index b9a0c2c3311a2dd2e1c60816a74956bfb5305720..dc6b4ee7a210f2f1a30a67987e5c778ce92f229b 100644
--- a/django_project/myapp/views/events_views.py
+++ b/django_project/myapp/views/events_views.py
@@ -1,7 +1,6 @@
 from django.shortcuts import render
 from django.conf import settings
-import rust_crud_api  # Make sure this matches your actual module name
-
+import rust_crud_api  # Custom Rust Pyo3 Library 🦀   
 def event_list_view(request):
     db_url = settings.DATABASE_URL
     try:
diff --git a/django_project/myapp/views/groupviews.py b/django_project/myapp/views/groupviews.py
index a4f28c956a6a2aae4b5bccb14c01eaca74b0076c..c5e274933ea387b00f842ecf81749e1fd7a528ca 100644
--- a/django_project/myapp/views/groupviews.py
+++ b/django_project/myapp/views/groupviews.py
@@ -5,6 +5,9 @@ import time
 import os
 import rust_crud_api # Custom Rust Pyo3 Library 🦀
 
+from django.contrib.auth.decorators import login_required
+
+
 db_url = settings.DATABASE_URL
 
 def group_list_view(request):
@@ -20,6 +23,25 @@ def group_list_view(request):
         context['error'] = f"An error occurred: {e}"
     return render(request, 'myapp/group_list.html', context)
 
+@login_required
+def group_join_view(request, group_id):
+    """
+    Join a group.
+    """
+    db_url = settings.DATABASE_URL
+    context = {}
+    if request.method == 'POST':
+        user_id = request.POST.get('user_id')
+        if not user_id or user_id == 'None':
+            context['error'] = "Invalid user_id: None"
+        else:
+            try:
+                rust_crud_api.add_user_to_group(db_url, int(group_id), int(user_id))
+                return redirect('group_list')
+            except Exception as e:
+                context['error'] = f"An error occurred: {e}"
+    return render(request, 'myapp/group_join.html', context)
+
 def group_create_view(request):
     """
     Create a new group.
@@ -28,11 +50,13 @@ def group_create_view(request):
     context = {}
     if request.method == 'POST':
         group_name = request.POST.get('name', '').strip()
+        tags_raw = request.POST.get('tags', '').strip()
+        tags = [tag.strip() for tag in tags_raw.split(',') if tag.strip()]
         if not group_name:
             context['error'] = "Group name is required."
             return render(request, 'myapp/group_create.html', context)
         try:
-            rust_crud_api.create_group(db_url, group_name)
+            rust_crud_api.create_group(db_url, group_name, tags)
             return redirect('group_list')
         except Exception as e:
             context['error'] = f"An error occurred: {e}"
@@ -98,24 +122,34 @@ def group_detail_view(request, group_id):
     db_url = settings.DATABASE_URL
     context = {}
 
-    if request.method == 'POST':
-        user_id = request.POST.get('user_id')  # might be None or 'None'
-
-        # Check for None *before* calling Rust
-        if not user_id or user_id == 'None':
-            context['error'] = "Invalid user_id: None"
-            return render(request, 'myapp/group_detail.html', context)
+    user_id = request.session.get('user_id')
+    is_member = False
+    members = []
 
+    if request.method == 'POST':
+        if not user_id:
+            return redirect('login')
         try:
-            # Now we safely do int(user_id) because we checked it's not None
-            result = rust_crud_api.add_user_to_group(db_url, int(group_id), int(user_id))
+            rust_crud_api.add_user_to_group(db_url, int(group_id), int(user_id))
         except Exception as e:
-            context['error'] = f"An error occurred: {e}"
-            return render(request, 'myapp/group_detail.html', context)
+            context['error'] = f"An error occurred while joining: {e}"
 
-    # Normal GET behavior...
-    return render(request, 'myapp/group_detail.html', context)
+    try:
+        group = rust_crud_api.get_group(db_url, int(group_id))
+        if not group:
+            context['error'] = "Group not found."
+        else:
+            context['group'] = group
+            context['user_id'] = user_id
+
+            members, _ = rust_crud_api.get_group_members(db_url, int(group_id))
+            context['members'] = members
+            is_member = any(m.id == int(user_id) for m in members) if user_id else False
+            context['is_member'] = is_member
+    except Exception as e:
+        context['error'] = f"An error occurred: {e}"
 
+    return render(request, 'myapp/group_detail.html', context)
 
 
 
diff --git a/django_project/myapp/views/userviews.py b/django_project/myapp/views/userviews.py
index f9ad56e0a2b56a2f342a1c9d1d6d3e32a862012d..422f9894a3efe6ed0983194603b9a261c03d7ff7 100644
--- a/django_project/myapp/views/userviews.py
+++ b/django_project/myapp/views/userviews.py
@@ -1,6 +1,7 @@
 from django.shortcuts import render, redirect
 from django.http import JsonResponse
 from django.conf import settings
+from myapp.forms import EmailLoginForm
 import time
 import os
 import rust_crud_api # Custom Rust Pyo3 Library 🦀
@@ -226,3 +227,17 @@ def edit_account_view(request):
     
     context['user'] = user
     return render(request, 'myapp/edit_account.html', context)
+
+def email_login_view(request):
+    form = EmailLoginForm(request.POST or None)
+    context = {'form': form}
+
+    if request.method == 'POST':
+        if form.is_valid():
+            user = form.user
+            request.session['user_id'] = user.id  # ✅ store manually
+            return redirect('group_list')  # or 'account', etc.
+        else:
+            context['form'] = form  # errors included
+
+    return render(request, 'myapp/login.html', context)
\ No newline at end of file
diff --git a/rust_crud_api/src/db/events.rs b/rust_crud_api/src/db/events.rs
index 635c79882cf450a27e5572b25b8e8fa123078b6a..38c5ce57cacfcbe12313a53ed5985d4dda23eb67 100644
--- a/rust_crud_api/src/db/events.rs
+++ b/rust_crud_api/src/db/events.rs
@@ -22,7 +22,7 @@ pub fn create_event(
 ) -> PyResult<()> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
 
-    let date_parsed = NaiveDate::parse_from_str(date, "%Y-%m-%d")
+    let date_parsed = NaiveDate::parse_from_str(date, "%Y-%m-%d") // Naive is raw date without timezone
         .map_err(|e| PyRuntimeError::new_err(format!("Invalid date: {}", e)))?;
     let time_parsed = NaiveTime::parse_from_str(time, "%H:%M:%S")
         .map_err(|e| PyRuntimeError::new_err(format!("Invalid time: {}", e)))?;
@@ -59,4 +59,31 @@ pub fn get_all_events(db_url: &str) -> PyResult<Vec<PyEvent>> {
     }
 
     Ok(events)
-}
\ No newline at end of file
+}
+
+#[pyfunction]
+pub fn get_event(db_url: &str, event_id: i32) -> PyResult<Option<PyEvent>> {
+    let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
+
+    let row_opt = client.query_opt(
+        "SELECT * FROM events WHERE id = $1",
+        &[&event_id]
+    ).map_err(pg_err)?;
+
+    if let Some(row) = row_opt {
+        let event = PyEvent {
+            id: row.get("id"),
+            title: row.get("title"),
+            description: row.get("description"),
+            location: row.get("location"),
+            date: row.get::<_, chrono::NaiveDate>("date").to_string(),
+            time: row.get::<_, chrono::NaiveTime>("time").to_string(),
+            created_by: row.get("created_by"),
+            group_id: row.get("group_id"),
+            created_at: row.get::<_, chrono::NaiveDateTime>("created_at").to_string(),
+        };
+        Ok(Some(event))
+    } else {
+        Ok(None)
+    }
+}
diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs
index 27f6d68a5ba95eb590dd5cdea644023b0dff313f..914919b52e4e52645ad1b1947ccd9bd6ffc713d8 100644
--- a/rust_crud_api/src/db/groups.rs
+++ b/rust_crud_api/src/db/groups.rs
@@ -10,11 +10,11 @@ fn pg_err(e: postgres::Error) -> PyErr {
 
 /// Create a group
 #[pyfunction]
-pub fn create_group(db_url: &str, name: &str) -> PyResult<()> {
+pub fn create_group(db_url: &str, name: &str, tags: Vec<String>) -> PyResult<()> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
     client.execute(
-        "INSERT INTO groups (name, member_count) VALUES ($1, $2)", 
-        &[&name, &0]  
+        "INSERT INTO groups (name, member_count, tags) VALUES ($1, $2, $3)", 
+        &[&name, &0, &tags]  
     ).map_err(pg_err)?;
     Ok(())
 }
@@ -23,16 +23,18 @@ pub fn create_group(db_url: &str, name: &str) -> PyResult<()> {
 #[pyfunction]
 pub fn get_group(db_url: &str, group_id: i32) -> PyResult<Option<Group>> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
+
     let row_opt = client.query_opt(
-        "SELECT id, name, member_count FROM groups WHERE id = $1",
+        "SELECT id, name, member_count, tags FROM groups WHERE id = $1",
         &[&group_id]
     ).map_err(pg_err)?;
-    
+
     if let Some(row) = row_opt {
         let group = Group {
             id: row.get(0),
             name: row.get(1),
             member_count: row.get(2),
+            tags: Some(row.get::<_, Option<Vec<String>>>(3).unwrap_or_default()),
         };
         Ok(Some(group))
     } else {
@@ -44,13 +46,14 @@ pub fn get_group(db_url: &str, group_id: i32) -> PyResult<Option<Group>> {
 #[pyfunction]
 pub fn get_all_groups(db_url: &str) -> PyResult<Vec<Group>> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
-    let rows = client.query("SELECT id, name, member_count FROM groups", &[])
+    let rows = client.query("SELECT id, name, member_count, tags FROM groups", &[])
         .map_err(pg_err)?;
     
     let groups = rows.into_iter().map(|row| Group {
         id: row.get(0),
         name: row.get(1),
         member_count: row.get(2),
+        tags: row.get(3),
     }).collect();
     
     Ok(groups)
@@ -122,7 +125,7 @@ pub fn delete_group(db_url: &str, group_id: i32) -> PyResult<bool> {
 pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
     let rows = client.query(
-        "SELECT id, name, member_count FROM groups WHERE name ILIKE $1",
+        "SELECT id, name, member_count, tags FROM groups WHERE name ILIKE $1",
         &[&format!("%{}%", query)] 
     ).map_err(pg_err)?;
 
@@ -131,12 +134,14 @@ pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> {
             id: Some(row.get(0)),
             name: row.get(1),
             member_count: row.get(2),
+            tags: row.get(3),
         })
         .collect();
 
     Ok(groups)
 }
 
+///Get the count of members in a group
 #[pyfunction]
 pub fn get_group_member_count(db_url: &str, group_id: i32) -> PyResult<i64> {
     let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?;
diff --git a/rust_crud_api/src/db/init.rs b/rust_crud_api/src/db/init.rs
index d6c4ae201836cf601efd6cc593a66f3f660755e6..f02e6dd4f23340186677d100bf9f241d4e57c0e4 100644
--- a/rust_crud_api/src/db/init.rs
+++ b/rust_crud_api/src/db/init.rs
@@ -27,7 +27,8 @@ pub fn init_db(db_url: &str) -> PyResult<()> {
         CREATE TABLE IF NOT EXISTS groups (
             id SERIAL PRIMARY KEY,
             name VARCHAR NOT NULL,
-            member_count INTEGER NOT NULL DEFAULT 0
+            member_count INTEGER NOT NULL DEFAULT 0,
+            tags TEXT[]
         );
 
         CREATE TABLE IF NOT EXISTS group_members (
diff --git a/rust_crud_api/src/db/posts.rs b/rust_crud_api/src/db/posts.rs
index 08219f8e37d37c87cc53eb12af3fa329e9dc19b4..a36a29bbcde33db25d34b014823d4474680e6e14 100644
--- a/rust_crud_api/src/db/posts.rs
+++ b/rust_crud_api/src/db/posts.rs
@@ -68,7 +68,11 @@ pub fn get_feed(db_url: &str) -> PyResult<Vec<Post>> {
         let user_name: Option<String> = Some(row.get(2));
         let content: String = row.get(3);
         let created_at: SystemTime = row.get(4); 
-        let created_at = DateTime::<Utc>::from(created_at).to_rfc3339();  
+        /// Convert SystemTime to DateTime<Utc>
+        let created_at = DateTime::<Utc>::from(created_at)
+            .format("%H:%M:%S/%d/%m/%Y")
+            .to_string();  
+
         posts.push(Post {
             id,
             user_id,
@@ -79,3 +83,4 @@ pub fn get_feed(db_url: &str) -> PyResult<Vec<Post>> {
     }
     Ok(posts)
 }
+
diff --git a/rust_crud_api/src/db/users.rs b/rust_crud_api/src/db/users.rs
index 2e34a3472dac121d078ea30edb97fd031215d526..ee95e1dc7c46b76a89d85ffa279520583c932ab7 100644
--- a/rust_crud_api/src/db/users.rs
+++ b/rust_crud_api/src/db/users.rs
@@ -6,10 +6,12 @@ use crate::auth::hash_password;
 use crate::auth::verify_password;
 use postgres::types::ToSql;
 
+
+/// Dont Delete this!
 fn pg_err(e: postgres::Error) -> PyErr {
     PyRuntimeError::new_err(e.to_string())
 }
-
+/// Create a user
 #[pyfunction]
 pub fn create_user(
     db_url: &str, name: &str, email: &str, password: &str, username: &str, studentid: i32, startyear: i32, endyear: i32, profilepicture: Option<&str>, firstlogin: bool) -> PyResult<()> {
@@ -104,6 +106,7 @@ pub fn get_all_users(db_url: &str) -> PyResult<Vec<User>> {
     new_endyear = None,
     new_profilepicture = None
 ))]
+
 pub fn update_user(
     db_url: &str,  
     user_id: i32,  
diff --git a/rust_crud_api/src/lib.rs b/rust_crud_api/src/lib.rs
index 05e21a9104ffb375f94f24b6166ed266b08cf65f..82821a1bd6d5d91a6b7f21265b72b5de2990cbfc 100644
--- a/rust_crud_api/src/lib.rs
+++ b/rust_crud_api/src/lib.rs
@@ -42,6 +42,9 @@ fn rust_crud_api(_py: Python, m: &PyModule) -> PyResult<()> {
     m.add_function(wrap_pyfunction!(db::posts::get_user_posts, m)?)?;
     m.add_function(wrap_pyfunction!(db::posts::get_group_posts, m)?)?;
     m.add_function(wrap_pyfunction!(db::posts::get_feed, m)?)?;
+
+    // Events
+    // Placeholder 
     Ok(())
 }
 
diff --git a/rust_crud_api/src/models/event.rs b/rust_crud_api/src/models/event.rs
index d7ab003147cbe52a84f33f8e96ad0b4bd4ee525f..2a7082bd142a919f9acad76feb5fe6c5fe1983d0 100644
--- a/rust_crud_api/src/models/event.rs
+++ b/rust_crud_api/src/models/event.rs
@@ -13,9 +13,9 @@ pub struct Event {
     #[pyo3(get, set)]
     pub location: String,
     #[pyo3(get, set)]
-    pub date: String, // or NaiveDate
+    pub date: String, // or NaiveDate - !Might not match up because Naive is being used elsewhere
     #[pyo3(get, set)]
-    pub time: String, // or NaiveTime
+    pub time: String, // or NaiveTime - !"" 
     #[pyo3(get, set)]
     pub created_by: i32,
     #[pyo3(get, set)]
diff --git a/rust_crud_api/src/models/group.rs b/rust_crud_api/src/models/group.rs
index c95423a4216085ec19154c84ce83eaf9140e1a0b..4c292689c29059f3f45160799d00eaaf0f9ede32 100644
--- a/rust_crud_api/src/models/group.rs
+++ b/rust_crud_api/src/models/group.rs
@@ -10,6 +10,8 @@ pub struct Group {
     pub name: String,
     #[pyo3(get, set)]
     pub member_count: i32,
+    #[pyo3(get, set)]
+    pub tags : Option<Vec<String>>,
     
 }