diff --git a/frontend/src/hooks/useGuests/index.tsx b/frontend/src/hooks/useGuests/index.tsx
index d69df315c5cc22c94ac88e6edf542f0bd76a5bf0..23f5a54f3c87d7818cb6949278e9444343e73265 100644
--- a/frontend/src/hooks/useGuests/index.tsx
+++ b/frontend/src/hooks/useGuests/index.tsx
@@ -4,6 +4,7 @@ import { parseIdentity, parseRole, fetchJsonOpts } from 'utils'
 
 const useGuests = () => {
   const [guests, setGuests] = useState<Guest[]>([])
+  const [loading, setLoading] = useState<boolean>(true)
 
   const getGuestsInfo = () =>
     fetch('/api/ui/v1/guests/', fetchJsonOpts())
@@ -28,8 +29,12 @@ const useGuests = () => {
             })
           )
         )
+        setLoading(false)
+      })
+      .catch(() => {
+        setGuests([])
+        setLoading(false)
       })
-      .catch(() => setGuests([]))
 
   const reloadGuests = () => {
     getGuestsInfo()
@@ -39,7 +44,7 @@ const useGuests = () => {
     getGuestsInfo()
   }, [])
 
-  return { guests, reloadGuests }
+  return { guests, reloadGuests, loading }
 }
 
 export default useGuests
diff --git a/frontend/src/routes/sponsor/frontpage/index.tsx b/frontend/src/routes/sponsor/frontpage/index.tsx
index 5036a661d31f45322f58c90ee27f3a2b7c930fc1..84bf384beec8237679f82aebde74233c08886392 100644
--- a/frontend/src/routes/sponsor/frontpage/index.tsx
+++ b/frontend/src/routes/sponsor/frontpage/index.tsx
@@ -17,6 +17,7 @@ import {
 import { styled } from '@mui/system'
 import { useState } from 'react'
 
+import Loading from 'components/loading'
 import Page from 'components/page'
 import { differenceInDays, format, isBefore } from 'date-fns'
 import { Guest, Role } from 'interfaces'
@@ -47,6 +48,7 @@ interface GuestTableProps {
 
 interface FrontPageProps {
   guests: Guest[]
+  loading: boolean
 }
 
 const StyledTableRow = styled(TableRow)({
@@ -401,15 +403,22 @@ const WaitingGuests = ({ persons }: GuestProps) => {
   )
 }
 
-function FrontPage({ guests }: FrontPageProps) {
+function FrontPage({ guests, loading }: FrontPageProps) {
   return (
     <Page pageWidth>
       <SponsorGuestButtons yourGuestsActive />
-      <InvitedGuests persons={guests} />
-      <br />
-      <WaitingGuests persons={guests} />
-      <br />
-      <ActiveGuests persons={guests} />
+
+      {loading ? (
+        <Loading />
+      ) : (
+        <>
+          <InvitedGuests persons={guests} />
+          <br />
+          <WaitingGuests persons={guests} />
+          <br />
+          <ActiveGuests persons={guests} />
+        </>
+      )}
     </Page>
   )
 }
diff --git a/frontend/src/routes/sponsor/index.tsx b/frontend/src/routes/sponsor/index.tsx
index 989d75489615475f365ff8ab5defae7c6ba6c08d..9e272f50cadf4c2fb58f32ae4537b75d93e61b74 100644
--- a/frontend/src/routes/sponsor/index.tsx
+++ b/frontend/src/routes/sponsor/index.tsx
@@ -5,7 +5,7 @@ import useGuests from 'hooks/useGuests'
 import GuestRoutes from './guest'
 
 function Sponsor() {
-  const { guests, reloadGuests } = useGuests()
+  const { guests, reloadGuests, loading } = useGuests()
 
   return (
     <Routes>
@@ -13,7 +13,10 @@ function Sponsor() {
         path="guest/:pid/*"
         element={<GuestRoutes reloadGuests={reloadGuests} />}
       />
-      <Route path="" element={<FrontPage guests={guests} />} />
+      <Route
+        path=""
+        element={<FrontPage guests={guests} loading={loading} />}
+      />
     </Routes>
   )
 }
diff --git a/greg/models.py b/greg/models.py
index 59d909bd4843f9ed0dc407deddeabe102092a460..1f3b6c4fb9ee2938067d992fda2cbb87f311e72f 100644
--- a/greg/models.py
+++ b/greg/models.py
@@ -709,7 +709,11 @@ class InvitationLink(BaseModel):
 
     uuid = models.UUIDField(null=False, default=uuid.uuid4, blank=False)
     invitation = models.ForeignKey(
-        "Invitation", on_delete=models.CASCADE, null=False, blank=False
+        "Invitation",
+        on_delete=models.CASCADE,
+        null=False,
+        blank=False,
+        related_name="invitation_links",
     )
     expire = models.DateTimeField(blank=False, null=False)
 
@@ -727,7 +731,13 @@ class Invitation(BaseModel):
     Deleting the InvitedPerson deletes the Invitation.
     """
 
-    role = models.ForeignKey("Role", null=False, blank=False, on_delete=models.CASCADE)
+    role = models.ForeignKey(
+        "Role",
+        null=False,
+        blank=False,
+        on_delete=models.CASCADE,
+        related_name="invitations",
+    )
 
     def __str__(self) -> str:
         return f"{self.__class__.__name__}(id={self.pk}, role={self.role})"
diff --git a/gregui/api/serializers/guest.py b/gregui/api/serializers/guest.py
index b7474eade11c78ef2552d2398c3e061eb9d1cb8b..ca63e30dc54bc0067a454cf3a84ca7818990ab87 100644
--- a/gregui/api/serializers/guest.py
+++ b/gregui/api/serializers/guest.py
@@ -1,4 +1,5 @@
 import datetime
+from typing import Literal
 
 from django.conf import settings
 from django.utils import timezone
@@ -288,3 +289,93 @@ class GuestSerializer(serializers.ModelSerializer):
             "invitation_status",
             "roles",
         ]
+
+
+class FrontPageGuestSerializer(serializers.ModelSerializer):
+    """
+    Serializer used for presenting guests to sponsors.
+    """
+
+    pid = CharField(source="id", read_only=True)
+    first = CharField(source="first_name", read_only=True)
+    last = CharField(source="last_name", read_only=True)
+    active = SerializerMethodField(source="active", read_only=True)
+    registered = BooleanField(source="is_registered", read_only=True)
+    verified = SerializerMethodField(source="verified", read_only=True)
+    invitation_status = SerializerMethodField(
+        source="get_invitation_status", read_only=True
+    )
+    roles = ExtendedRoleSerializer(many=True, read_only=True)
+
+    def get_active(self, obj: Person) -> bool:
+        return obj.is_registered and self.get_verified(obj)
+
+    def get_verified(self, obj: Person) -> bool:
+        return (
+            len(
+                [
+                    x
+                    for x in obj.identities.all()
+                    if x.type
+                    in [
+                        Identity.IdentityType.NORWEGIAN_NATIONAL_ID_NUMBER,
+                        Identity.IdentityType.PASSPORT_NUMBER,
+                    ]
+                    and x.verified_at
+                    and x.verified_at <= timezone.now()
+                ]
+            )
+            >= 1
+        )
+
+    def get_invitation_status(
+        self, obj: Person
+    ) -> Literal["active", "expired", "invalidEmail", "none"]:
+
+        private_email = next(
+            iter(
+                [
+                    x
+                    for x in obj.identities.all()
+                    if x.type == Identity.IdentityType.PRIVATE_EMAIL
+                ]
+            ),
+            None,
+        )
+
+        if private_email and private_email.invalid:
+            return "invalidEmail"
+
+        invitations = [
+            item
+            for sublist in [list(x.invitations.all()) for x in obj.roles.all()]
+            for item in sublist
+        ]
+
+        # Get all invitation_links from all invitations and flatten them
+        invitation_links = [
+            item
+            for sublist in [list(x.invitation_links.all()) for x in invitations]
+            for item in sublist
+        ]
+
+        non_expired_links = [x for x in invitation_links if x.expire > timezone.now()]
+
+        if len(non_expired_links) > 0:
+            return "active"
+        if len(invitation_links) > 0:
+            return "expired"
+        return "none"
+
+    class Meta:
+        model = Person
+        fields = [
+            "pid",
+            "first",
+            "last",
+            "active",
+            "registered",
+            "verified",
+            "invitation_status",
+            "roles",
+        ]
diff --git a/gregui/api/views/person.py b/gregui/api/views/person.py
index 4cfbafbf21f9db4975c124c3c2b1880fbb50a5e6..c2a06e138118e01063b32fd8a82d6b51e1536c20 100644
--- a/gregui/api/views/person.py
+++ b/gregui/api/views/person.py
@@ -1,5 +1,4 @@
-from rest_framework import mixins
-from rest_framework import status
+from rest_framework import mixins, status
 from rest_framework.authentication import SessionAuthentication, BasicAuthentication
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
@@ -11,6 +10,7 @@ from greg.utils import is_identity_duplicate
 from gregui import validation
 from gregui.api.serializers.guest import (
     GuestSerializer,
+    FrontPageGuestSerializer,
     create_identity_or_update,
 )
 from gregui.api.serializers.identity import IdentityDuplicateError
@@ -121,7 +121,7 @@ class GuestInfoViewSet(mixins.ListModelMixin, GenericViewSet):
 
     authentication_classes = [SessionAuthentication, BasicAuthentication]
     permission_classes = [IsAuthenticated, IsSponsor]
-    serializer_class = GuestSerializer
+    serializer_class = FrontPageGuestSerializer
 
     def get_queryset(self):
         """
@@ -135,6 +135,16 @@ class GuestInfoViewSet(mixins.ListModelMixin, GenericViewSet):
         units = user.sponsor.get_allowed_units()
         return (
             Person.objects.filter(roles__orgunit__in=list(units))
+            .prefetch_related(
+                "identities",
+                "roles",
+                "roles__sponsor",
+                "roles__orgunit",
+                "roles__person",
+                "roles__type",
+                "roles__invitations",
+                "roles__invitations__invitation_links",
+            )
             .distinct()
             .order_by("id")
         )