diff --git a/cloudformation/iam.yml b/cloudformation/iam.yml
index 11b8e05a..38651036 100644
--- a/cloudformation/iam.yml
+++ b/cloudformation/iam.yml
@@ -78,6 +78,8 @@ Resources:
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-room-requests-status
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-linkry
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-keys
+              - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-sig-member-details
+              - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-sig-details
               # Index accesses
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-stripe-links/index/*
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-events/index/*
@@ -99,6 +101,14 @@ Resources:
             Resource:
               - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-cache
 
+          - Sid: DynamoDBRateLimitTableAccess
+            Effect: Allow
+            Action:
+              - dynamodb:DescribeTable
+              - dynamodb:UpdateItem
+            Resource:
+              - Fn::Sub: arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/infra-core-api-rate-limiter
+
           - Sid: DynamoDBAuditLogTableAccess
             Effect: Allow
             Action:
diff --git a/src/api/functions/siglead.ts b/src/api/functions/siglead.ts
new file mode 100644
index 00000000..83316c96
--- /dev/null
+++ b/src/api/functions/siglead.ts
@@ -0,0 +1,172 @@
+import {
+  AttributeValue,
+  DynamoDBClient,
+  GetItemCommand,
+  PutItemCommand,
+  PutItemCommandInput,
+  QueryCommand,
+  ScanCommand,
+} from "@aws-sdk/client-dynamodb";
+import { unmarshall } from "@aws-sdk/util-dynamodb";
+import { DatabaseInsertError } from "common/errors/index.js";
+import { OrganizationList, orgIds2Name } from "common/orgs.js";
+import {
+  SigDetailRecord,
+  SigMemberCount,
+  SigMemberRecord,
+  SigMemberUpdateRecord,
+} from "common/types/siglead.js";
+import { transformSigLeadToURI } from "common/utils.js";
+import { KeyObject } from "crypto";
+import { string } from "zod";
+
+export async function fetchMemberRecords(
+  sigid: string,
+  tableName: string,
+  dynamoClient: DynamoDBClient,
+) {
+  const fetchSigMemberRecords = new QueryCommand({
+    TableName: tableName,
+    KeyConditionExpression: "#sigid = :accessVal",
+    ExpressionAttributeNames: {
+      "#sigid": "sigGroupId",
+    },
+    ExpressionAttributeValues: {
+      ":accessVal": { S: sigid },
+    },
+    ScanIndexForward: false,
+  });
+
+  const result = await dynamoClient.send(fetchSigMemberRecords);
+
+  // Process the results
+  return (result.Items || []).map((item) => {
+    const unmarshalledItem = unmarshall(item);
+    return unmarshalledItem as SigMemberRecord;
+  });
+}
+
+export async function fetchSigDetail(
+  sigid: string,
+  tableName: string,
+  dynamoClient: DynamoDBClient,
+) {
+  const fetchSigDetail = new QueryCommand({
+    TableName: tableName,
+    KeyConditionExpression: "#sigid = :accessVal",
+    ExpressionAttributeNames: {
+      "#sigid": "sigid",
+    },
+    ExpressionAttributeValues: {
+      ":accessVal": { S: sigid },
+    },
+    ScanIndexForward: false,
+  });
+
+  const result = await dynamoClient.send(fetchSigDetail);
+
+  // Process the results
+  return (result.Items || [{}]).map((item) => {
+    const unmarshalledItem = unmarshall(item);
+
+    // Strip '#' from access field
+    delete unmarshalledItem.leadGroupId;
+    delete unmarshalledItem.memberGroupId;
+
+    return unmarshalledItem as SigDetailRecord;
+  })[0];
+}
+
+// select count(sigid)
+// from table
+// groupby sigid
+export async function fetchSigCounts(
+  sigMemberTableName: string,
+  dynamoClient: DynamoDBClient,
+) {
+  const scan = new ScanCommand({
+    TableName: sigMemberTableName,
+    ProjectionExpression: "sigGroupId",
+  });
+
+  const result = await dynamoClient.send(scan);
+
+  const counts: Record<string, number> = {};
+  // Object.entries(orgIds2Name).forEach(([id, _]) => {
+  //   counts[id] = 0;
+  // });
+
+  (result.Items || []).forEach((item) => {
+    const sigGroupId = item.sigGroupId?.S;
+    if (sigGroupId) {
+      counts[sigGroupId] = (counts[sigGroupId] || 0) + 1;
+    }
+  });
+
+  const countsArray: SigMemberCount[] = Object.entries(counts).map(
+    ([id, count]) => ({
+      sigid: id,
+      signame: orgIds2Name[id],
+      count,
+    }),
+  );
+  console.log(countsArray);
+  return countsArray;
+}
+
+export async function addMemberToSigDynamo(
+  sigMemberTableName: string,
+  sigMemberUpdateRequest: SigMemberUpdateRecord,
+  dynamoClient: DynamoDBClient,
+) {
+  const item: Record<string, AttributeValue> = {};
+  Object.entries(sigMemberUpdateRequest).forEach(([k, v]) => {
+    item[k] = { S: v };
+  });
+
+  // put into table
+  const put = new PutItemCommand({
+    Item: item,
+    ReturnConsumedCapacity: "TOTAL",
+    TableName: sigMemberTableName,
+  });
+  try {
+    const response = await dynamoClient.send(put);
+    console.log(response);
+  } catch (e) {
+    console.error("Put to dynamo db went wrong.");
+    throw e;
+  }
+
+  // fetch from db and check if fetched item update time = input item update time
+  const validatePutQuery = new GetItemCommand({
+    TableName: sigMemberTableName,
+    Key: {
+      sigGroupId: { S: sigMemberUpdateRequest.sigGroupId },
+      email: { S: sigMemberUpdateRequest.email },
+    },
+    ProjectionExpression: "updatedAt",
+  });
+
+  try {
+    const response = await dynamoClient.send(validatePutQuery);
+    const item = response.Item;
+
+    if (!item || !item.updatedAt?.S) {
+      throw new Error("Item not found or missing 'updatedAt'");
+    }
+
+    if (item.updatedAt.S !== sigMemberUpdateRequest.updatedAt) {
+      throw new DatabaseInsertError({
+        message: "The member exists, but was updated by someone else!",
+      });
+    }
+  } catch (e) {
+    console.error("Validate DynamoDB get went wrong.", e);
+    throw e;
+  }
+}
+
+export async function addMemberToSigEntra() {
+  // uuid validation not implemented yet
+}
diff --git a/src/api/index.ts b/src/api/index.ts
index 5cd222b5..bc1e682a 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -25,6 +25,7 @@ import * as dotenv from "dotenv";
 import iamRoutes from "./routes/iam.js";
 import ticketsPlugin from "./routes/tickets.js";
 import linkryRoutes from "./routes/linkry.js";
+import sigleadRoutes from "./routes/siglead.js";
 import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
 import NodeCache from "node-cache";
 import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
@@ -289,6 +290,7 @@ async function init(prettyPrint: boolean = false) {
       api.register(linkryRoutes, { prefix: "/linkry" });
       api.register(mobileWalletRoute, { prefix: "/mobileWallet" });
       api.register(stripeRoutes, { prefix: "/stripe" });
+      api.register(sigleadRoutes, { prefix: "/siglead" });
       api.register(roomRequestRoutes, { prefix: "/roomRequests" });
       api.register(logsPlugin, { prefix: "/logs" });
       api.register(apiKeyRoute, { prefix: "/apiKey" });
diff --git a/src/api/routes/siglead.ts b/src/api/routes/siglead.ts
new file mode 100644
index 00000000..1b27a3e8
--- /dev/null
+++ b/src/api/routes/siglead.ts
@@ -0,0 +1,151 @@
+import { FastifyPluginAsync } from "fastify";
+import { DatabaseFetchError } from "../../common/errors/index.js";
+
+import { genericConfig } from "../../common/config.js";
+
+import {
+  SigDetailRecord,
+  SigleadGetRequest,
+  SigMemberCount,
+  SigMemberRecord,
+  SigMemberUpdateRecord,
+} from "common/types/siglead.js";
+import {
+  addMemberToSigDynamo,
+  fetchMemberRecords,
+  fetchSigCounts,
+  fetchSigDetail,
+} from "api/functions/siglead.js";
+import { intersection } from "api/plugins/auth.js";
+import { request } from "http";
+
+const sigleadRoutes: FastifyPluginAsync = async (fastify, _options) => {
+  const limitedRoutes: FastifyPluginAsync = async (fastify) => {
+    /*fastify.register(rateLimiter, {
+      limit: 30,
+      duration: 60,
+      rateLimitIdentifier: "linkry",
+    });*/
+
+    fastify.get<SigleadGetRequest>(
+      "/sigmembers/:sigid",
+      {
+        onRequest: async (request, reply) => {
+          /*await fastify.authorize(request, reply, [
+            AppRoles.LINKS_MANAGER,
+            AppRoles.LINKS_ADMIN,
+          ]);*/
+        },
+      },
+      async (request, reply) => {
+        const { sigid } = request.params;
+        const tableName = genericConfig.SigleadDynamoSigMemberTableName;
+
+        // First try-catch: Fetch owner records
+        let memberRecords: SigMemberRecord[];
+        try {
+          memberRecords = await fetchMemberRecords(
+            sigid,
+            tableName,
+            fastify.dynamoClient,
+          );
+        } catch (error) {
+          request.log.error(
+            `Failed to fetch member records: ${error instanceof Error ? error.toString() : "Unknown error"}`,
+          );
+          throw new DatabaseFetchError({
+            message: "Failed to fetch member records from Dynamo table.",
+          });
+        }
+
+        // Send the response
+        reply.code(200).send(memberRecords);
+      },
+    );
+
+    fastify.get<SigleadGetRequest>(
+      "/sigdetail/:sigid",
+      {
+        onRequest: async (request, reply) => {
+          /*await fastify.authorize(request, reply, [
+              AppRoles.LINKS_MANAGER,
+              AppRoles.LINKS_ADMIN,
+            ]);*/
+        },
+      },
+      async (request, reply) => {
+        const { sigid } = request.params;
+        const tableName = genericConfig.SigleadDynamoSigDetailTableName;
+
+        // First try-catch: Fetch owner records
+        let sigDetail: SigDetailRecord;
+        try {
+          sigDetail = await fetchSigDetail(
+            sigid,
+            tableName,
+            fastify.dynamoClient,
+          );
+        } catch (error) {
+          request.log.error(
+            `Failed to fetch sig detail record: ${error instanceof Error ? error.toString() : "Unknown error"}`,
+          );
+          throw new DatabaseFetchError({
+            message: "Failed to fetch sig detail record from Dynamo table.",
+          });
+        }
+
+        // Send the response
+        reply.code(200).send(sigDetail);
+      },
+    );
+
+    // fetch sig count
+    fastify.get<SigleadGetRequest>("/sigcount", async (request, reply) => {
+      // First try-catch: Fetch owner records
+      let sigMemCounts: SigMemberCount[];
+      try {
+        sigMemCounts = await fetchSigCounts(
+          genericConfig.SigleadDynamoSigMemberTableName,
+          fastify.dynamoClient,
+        );
+      } catch (error) {
+        request.log.error(
+          `Failed to fetch sig member counts record: ${error instanceof Error ? error.toString() : "Unknown error"}`,
+        );
+        throw new DatabaseFetchError({
+          message:
+            "Failed to fetch sig member counts record from Dynamo table.",
+        });
+      }
+
+      // Send the response
+      reply.code(200).send(sigMemCounts);
+    });
+
+    // add member
+    fastify.post<{ Body: SigMemberUpdateRecord }>(
+      "/addMember",
+      async (request, reply) => {
+        try {
+          await addMemberToSigDynamo(
+            genericConfig.SigleadDynamoSigMemberTableName,
+            request.body,
+            fastify.dynamoClient,
+          );
+        } catch (error) {
+          request.log.error(
+            `Failed to add member: ${error instanceof Error ? error.toString() : "Unknown error"}`,
+          );
+          throw new DatabaseFetchError({
+            message: "Failed to add sig member record to Dynamo table.",
+          });
+        }
+        reply.code(200);
+      },
+    );
+  };
+
+  fastify.register(limitedRoutes);
+};
+
+export default sigleadRoutes;
diff --git a/src/common/config.ts b/src/common/config.ts
index 0076dfb9..23f85782 100644
--- a/src/common/config.ts
+++ b/src/common/config.ts
@@ -48,6 +48,10 @@ export type GenericConfigType = {
   EntraReadOnlySecretName: string;
   AuditLogTable: string;
   ApiKeyTable: string;
+
+  RateLimiterDynamoTableName: string;
+  SigleadDynamoSigDetailTableName: string;
+  SigleadDynamoSigMemberTableName: string;
 };
 
 type EnvironmentConfigType = {
@@ -63,6 +67,8 @@ export const commChairsTestingGroupId = "d714adb7-07bb-4d4d-a40a-b035bc2a35a3";
 export const commChairsGroupId = "105e7d32-7289-435e-a67a-552c7f215507";
 export const miscTestingGroupId = "ff25ec56-6a33-420d-bdb0-51d8a3920e46";
 
+export const orgsGroupId = "0b3be7c2-748e-46ce-97e7-cf86f9ca7337";
+
 const genericConfig: GenericConfigType = {
   EventsDynamoTableName: "infra-core-api-events",
   StripeLinksDynamoTableName: "infra-core-api-stripe-links",
@@ -86,6 +92,10 @@ const genericConfig: GenericConfigType = {
   RoomRequestsStatusTableName: "infra-core-api-room-requests-status",
   AuditLogTable: "infra-core-api-audit-log",
   ApiKeyTable: "infra-core-api-keys",
+
+  RateLimiterDynamoTableName: "infra-core-api-rate-limiter",
+  SigleadDynamoSigDetailTableName: "infra-core-api-sig-details",
+  SigleadDynamoSigMemberTableName: "infra-core-api-sig-member-details",
 } as const;
 
 const environmentConfig: EnvironmentConfigType = {
diff --git a/src/common/roles.ts b/src/common/roles.ts
index cb99cf6f..acbeee73 100644
--- a/src/common/roles.ts
+++ b/src/common/roles.ts
@@ -3,6 +3,7 @@ export const runEnvironments = ["dev", "prod"] as const;
 export type RunEnvironment = (typeof runEnvironments)[number];
 export enum AppRoles {
   EVENTS_MANAGER = "manage:events",
+  SIGLEAD_MANAGER = "manage:siglead",
   TICKETS_SCANNER = "scan:tickets",
   TICKETS_MANAGER = "manage:tickets",
   IAM_ADMIN = "admin:iam",
@@ -17,5 +18,8 @@ export enum AppRoles {
   MANAGE_ORG_API_KEYS = "manage:orgApiKey"
 }
 export const allAppRoles = Object.values(AppRoles).filter(
-  (value) => typeof value === "string",
+  (value) => typeof value === "string", 
 );
+
+
+  
\ No newline at end of file
diff --git a/src/common/types/siglead.ts b/src/common/types/siglead.ts
new file mode 100644
index 00000000..9da5b696
--- /dev/null
+++ b/src/common/types/siglead.ts
@@ -0,0 +1,34 @@
+export type SigDetailRecord = {
+  sigid: string;
+  signame: string;
+  description: string;
+};
+
+export type SigMemberRecord = {
+  sigGroupId: string;
+  email: string;
+  designation: string;
+  memberName: string;
+};
+
+export type SigleadGetRequest = {
+  Params: { sigid: string };
+  Querystring: undefined;
+  Body: undefined;
+};
+
+export type SigMemberCount = {
+  sigid: string;
+  signame: string;
+  count: number;
+};
+
+export type SigMemberUpdateRecord = {
+  sigGroupId: string;
+  email: string;
+  id: string;
+  memberName: string;
+  designation: string;
+  createdAt: string;
+  updatedAt: string;
+}
\ No newline at end of file
diff --git a/src/common/utils.ts b/src/common/utils.ts
index 786c998f..5efddccc 100644
--- a/src/common/utils.ts
+++ b/src/common/utils.ts
@@ -12,3 +12,60 @@ export function transformCommaSeperatedName(name: string) {
   }
   return name;
 }
+
+const notUnreservedCharsRegex = /[^a-zA-Z0-9\-._~]/g;
+const reservedCharsRegex = /[:\/?#\[\]@!$&'()*+,;=]/g;
+/**
+ * Transforms an organization name (sig lead) into a URI-friendly format.
+ * The function performs the following transformations:
+ * - Removes characters that are reserved or not unreserved.
+ * - Adds spaces between camel case words.
+ * - Converts reserved characters to spaces.
+ * - Converts all characters to lowercase and replaces all types of whitespace with hyphens.
+ * - Replaces any sequence of repeated hyphens with a single hyphen.
+ * - Refer to RFC 3986 https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
+ *
+ * @param {string} org - The organization (sig lead) name to be transformed.
+ * @returns {string} - The transformed organization name, ready for use as a URL.
+ */
+export function transformSigLeadToURI(org: string) {
+  // console.log(`org\t${org}`)
+  org = org
+    // change not reserved chars to spaces
+    .trim()
+    .replace(notUnreservedCharsRegex, " ")
+    .trim()
+    .replace(/\s/g, "-")
+
+    // remove all that is reserved or not unreserved
+    .replace(reservedCharsRegex, "")
+
+    // convert SIG -> sig for camel case
+    .replace(/SIG/g, "sig")
+
+    // add hyphen for camel case
+    .replace(/([a-z])([A-Z])/g, "$1-$2")
+
+    // lower
+    .toLowerCase()
+    
+    // add spaces between chars and numbers (seq2seq -> seq-2-seq)
+    .replace(/(?<=[a-z])([0-9]+)(?=[a-z])/g, "-$1-")
+
+    // remove duplicate hyphens
+    .replace(/-{2,}/g, "-");
+
+  return org === "-" ? "" : org;
+}
+
+export function getTimeInFormat() {
+  const date = new Date();
+  const year = date.getUTCFullYear();
+  const month = String(date.getUTCMonth() + 1).padStart(2, '0');
+  const day = String(date.getUTCDate()).padStart(2, '0');
+  const hours = String(date.getUTCHours()).padStart(2, '0');
+  const minutes = String(date.getUTCMinutes()).padStart(2, '0');
+  const seconds = String(date.getUTCSeconds()).padStart(2, '0');
+
+  return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}Z`;
+}
diff --git a/src/ui/Router.tsx b/src/ui/Router.tsx
index 0276bb31..28927859 100644
--- a/src/ui/Router.tsx
+++ b/src/ui/Router.tsx
@@ -5,6 +5,7 @@ import {
   RouterProvider,
   useLocation,
 } from "react-router-dom";
+
 import { AcmAppShell } from "./components/AppShell";
 import { useAuth } from "./components/AuthContext";
 import AuthCallback from "./components/AuthContext/AuthCallbackHandler.page";
@@ -24,6 +25,12 @@ import { ManageIamPage } from "./pages/iam/ManageIam.page";
 import { ManageProfilePage } from "./pages/profile/ManageProfile.page";
 import { ManageStripeLinksPage } from "./pages/stripe/ViewLinks.page";
 import { ManageRoomRequestsPage } from "./pages/roomRequest/RoomRequestLanding.page";
+import { EditSigLeadsPage } from "./pages/siglead/EditSigLeads.page";
+import { ManageSigLeadsPage } from "./pages/siglead/ManageSigLeads.page";
+import {
+  AddMemberToSigPage,
+  ViewSigLeadPage,
+} from "./pages/siglead/ViewSigLead.page";
 import { ViewRoomRequest } from "./pages/roomRequest/ViewRoomRequest.page";
 import { ViewLogsPage } from "./pages/logs/ViewLogs.page";
 import { TermsOfService } from "./pages/tos/TermsOfService.page";
@@ -187,6 +194,22 @@ const authenticatedRouter = createBrowserRouter([
     path: "/stripe",
     element: <ManageStripeLinksPage />,
   },
+  {
+    path: "/siglead-management",
+    element: <ManageSigLeadsPage />,
+  },
+  {
+    path: "/siglead-management/edit",
+    element: <EditSigLeadsPage />,
+  },
+  {
+    path: "/siglead-management/:sigId",
+    element: <ViewSigLeadPage />,
+  },
+  {
+    path: "/siglead-management/:sigId/addMember",
+    element: <AddMemberToSigPage />,
+  },
   {
     path: "/roomRequests",
     element: <ManageRoomRequestsPage />,
diff --git a/src/ui/components/AppShell/index.tsx b/src/ui/components/AppShell/index.tsx
index 335f0b00..59ca6bfe 100644
--- a/src/ui/components/AppShell/index.tsx
+++ b/src/ui/components/AppShell/index.tsx
@@ -21,6 +21,7 @@ import {
   IconDoor,
   IconHistory,
   IconKey,
+  IconUsers,
 } from "@tabler/icons-react";
 import { ReactNode } from "react";
 import { useNavigate } from "react-router-dom";
@@ -76,6 +77,13 @@ export const navItems = [
     description: null,
     validRoles: [AppRoles.ROOM_REQUEST_CREATE, AppRoles.ROOM_REQUEST_UPDATE],
   },
+  {
+    link: "/siglead-management",
+    name: "SigLead",
+    icon: IconUsers,
+    description: null,
+    validRoles: [AppRoles.SIGLEAD_MANAGER],
+  },
   {
     link: "/linkry",
     name: "Link Shortener",
diff --git a/src/ui/pages/siglead/EditSigLeads.page.tsx b/src/ui/pages/siglead/EditSigLeads.page.tsx
new file mode 100644
index 00000000..c5c03d38
--- /dev/null
+++ b/src/ui/pages/siglead/EditSigLeads.page.tsx
@@ -0,0 +1,116 @@
+import { Title, TextInput, Button, Container, Group } from "@mantine/core";
+import { useForm, zodResolver } from "@mantine/form";
+import { notifications } from "@mantine/notifications";
+import React, { useState } from "react";
+import { useNavigate } from "react-router-dom";
+import { z } from "zod";
+import { AuthGuard } from "@ui/components/AuthGuard";
+import { useApi } from "@ui/util/api";
+import { AppRoles } from "@common/roles";
+import { transformSigLeadToURI } from "@common/utils";
+
+const baseSigSchema = z.object({
+  signame: z
+    .string()
+    .min(1, "Title is required")
+    .regex(
+      /^[a-zA-Z0-9]+$/,
+      "Sig name should only contain alphanumeric characters",
+    ),
+  description: z.string().min(1, "Description is required"),
+});
+
+type SigPostRequest = z.infer<typeof baseSigSchema>;
+
+export const EditSigLeadsPage: React.FC = () => {
+  const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
+  const navigate = useNavigate();
+  const api = useApi("core");
+
+  const form = useForm<SigPostRequest>({
+    validate: zodResolver(baseSigSchema),
+    initialValues: {
+      signame: "",
+      description: "",
+    },
+  });
+
+  const checkSigId = async (signame: string) => {
+    try {
+      const sigid = transformSigLeadToURI(signame);
+      const result = await api.get(`/api/v1/siglead/sigdetail/${sigid}`);
+      return result.data;
+    } catch (error) {
+      console.error("Error validating if sigid already exists", error);
+      notifications.show({
+        message: `Error validating if sigid already exists`,
+      });
+    }
+  };
+
+  const handleSubmit = async (sigdetails: SigPostRequest) => {
+    try {
+      setIsSubmitting(true);
+      const found = await checkSigId(sigdetails.signame);
+      if (found) {
+        form.setErrors({
+          signame: "This signame is reserved already.",
+        });
+        setIsSubmitting(false);
+        return;
+      }
+      notifications.show({
+        message: `This will eventually make to a post request with signame: 
+            ${sigdetails.signame} and description: ${sigdetails.description}  
+            `,
+      });
+      //Post...
+      navigate("/siglead-management");
+    } catch (error) {
+      setIsSubmitting(false);
+      console.error("Error creating sig:", error);
+      notifications.show({
+        message: "Failed to create sig, please try again.",
+      });
+    }
+  };
+
+  return (
+    <AuthGuard
+      resourceDef={{ service: "core", validRoles: [AppRoles.IAM_ADMIN] }}
+    >
+      <Container>
+        <Title order={1}>Registering a new Sig</Title>
+        <form onSubmit={form.onSubmit(handleSubmit)}>
+          <TextInput
+            label="SIG Name"
+            description="Enter your sig name"
+            withAsterisk
+            mt="xl"
+            {...form.getInputProps("signame")}
+          />
+          <TextInput
+            label="Description"
+            description="Enter the description of your SIG"
+            withAsterisk
+            mt="xl"
+            {...form.getInputProps("description")}
+          />
+          <Group mt="xl">
+            <Button
+              variant="outline"
+              onClick={() => navigate("/siglead-management")}
+            >
+              {" "}
+              Cancel{" "}
+            </Button>
+            <Button type="submit" variant="gradient">
+              {" "}
+              Submit{" "}
+            </Button>
+          </Group>
+        </form>
+      </Container>
+    </AuthGuard>
+  );
+};
diff --git a/src/ui/pages/siglead/ManageSigLeads.page.tsx b/src/ui/pages/siglead/ManageSigLeads.page.tsx
new file mode 100644
index 00000000..ced9bccd
--- /dev/null
+++ b/src/ui/pages/siglead/ManageSigLeads.page.tsx
@@ -0,0 +1,67 @@
+import { Title, Button, Container, Group } from "@mantine/core";
+import { useDisclosure } from "@mantine/hooks";
+import { DateTimePicker } from "@mantine/dates";
+import { useForm, zodResolver } from "@mantine/form";
+import { notifications } from "@mantine/notifications";
+import dayjs from "dayjs";
+import React, { useEffect, useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
+import { z } from "zod";
+import { AuthGuard } from "@ui/components/AuthGuard";
+import { getRunEnvironmentConfig } from "@ui/config";
+import { useApi } from "@ui/util/api";
+import { OrganizationList as orgList } from "@common/orgs";
+import { AppRoles } from "@common/roles";
+import { ScreenComponent } from "./SigScreenComponents";
+import { transformSigLeadToURI } from "@common/utils";
+import {
+  SigDetailRecord,
+  SigleadGetRequest,
+  SigMemberCount,
+  SigMemberRecord,
+} from "@common/types/siglead";
+
+export const ManageSigLeadsPage: React.FC = () => {
+  const [SigMemberCounts, setSigMemberCounts] = useState<SigMemberCount[]>([]);
+  const navigate = useNavigate();
+  const api = useApi("core");
+
+  useEffect(() => {
+    const getMemberCounts = async () => {
+      try {
+        const sigMemberCountsRequest = await api.get(
+          `/api/v1/siglead/sigcount`,
+        );
+        setSigMemberCounts(sigMemberCountsRequest.data);
+      } catch (error) {
+        console.error("Error fetching sig member counts:", error);
+        notifications.show({
+          message: "Failed to fetch sig member counts, please try again.",
+        });
+      }
+    };
+    getMemberCounts();
+  }, []);
+
+  return (
+    <AuthGuard
+      resourceDef={{ service: "core", validRoles: [AppRoles.IAM_ADMIN] }}
+    >
+      <Container>
+        <Group flex="auto">
+          <Title order={2}>SigLead Management System</Title>
+          <Button
+            ml="auto"
+            variant="gradient"
+            onClick={() => navigate("/siglead-management/edit")}
+          >
+            Add a Sig
+          </Button>
+        </Group>
+
+        <ScreenComponent SigMemberCounts={SigMemberCounts} />
+        {/* <SigTable /> */}
+      </Container>
+    </AuthGuard>
+  );
+};
diff --git a/src/ui/pages/siglead/SigScreenComponents.tsx b/src/ui/pages/siglead/SigScreenComponents.tsx
new file mode 100644
index 00000000..50d45eaf
--- /dev/null
+++ b/src/ui/pages/siglead/SigScreenComponents.tsx
@@ -0,0 +1,76 @@
+import React, { useEffect, useMemo, useState } from "react";
+import { OrganizationList } from "@common/orgs";
+import { NavLink, Paper } from "@mantine/core";
+import { IconUsersGroup } from "@tabler/icons-react";
+import { useNavigate } from "react-router-dom";
+import { SigMemberCount } from "@common/types/siglead";
+
+const renderSigLink = (sigMemCount: SigMemberCount, index: number) => {
+  const navigate = useNavigate();
+
+  const color =
+    "light-dark(var(--mantine-color-black), var(--mantine-color-white))";
+  const size = "18px";
+  const name = sigMemCount.signame;
+  const id = sigMemCount.sigid;
+  const count = sigMemCount.count;
+  return (
+    <NavLink
+      onClick={() => navigate(`./${id}`)}
+      active={index % 2 === 0}
+      label={name}
+      color="var(--mantine-color-blue-light)"
+      variant="filled"
+      rightSection={
+        <div
+          style={{
+            display: "flex",
+            alignItems: "center",
+            gap: "4px",
+            color: `${color}`,
+            fontSize: `${size}`,
+          }}
+        >
+          <span>{count}</span>
+          <IconUsersGroup />
+        </div>
+      }
+      styles={{
+        label: {
+          color: `${color}`,
+          fontSize: `${size}`,
+        },
+      }}
+    />
+  );
+};
+
+type props = {
+  SigMemberCounts: SigMemberCount[];
+};
+
+export const ScreenComponent: React.FC<props> = ({ SigMemberCounts }) => {
+  return (
+    <>
+      <Paper
+        shadow="xs"
+        p="sm"
+        style={{
+          display: "flex",
+          justifyContent: "space-between",
+          alignItems: "center",
+          fontWeight: "bold",
+          borderRadius: "8px",
+          padding: "10px 16px",
+          marginBottom: "8px",
+          fontSize: "22px",
+        }}
+      >
+        <span>Organization</span>
+        <span>Member Count</span>
+      </Paper>
+      {/* {OrganizationList.map(renderSigLink)} */}
+      {SigMemberCounts.map(renderSigLink)}
+    </>
+  );
+};
diff --git a/src/ui/pages/siglead/ViewSigLead.page.tsx b/src/ui/pages/siglead/ViewSigLead.page.tsx
new file mode 100644
index 00000000..5e5db651
--- /dev/null
+++ b/src/ui/pages/siglead/ViewSigLead.page.tsx
@@ -0,0 +1,266 @@
+import {
+  Title,
+  Box,
+  Button,
+  Container,
+  Transition,
+  useMantineColorScheme,
+  Table,
+  Group,
+  Stack,
+} from "@mantine/core";
+
+import { notifications } from "@mantine/notifications";
+import React, { FC, useEffect, useState } from "react";
+import { useNavigate, useParams } from "react-router-dom";
+import { AuthGuard } from "@ui/components/AuthGuard";
+import { useApi } from "@ui/util/api";
+import { AppRoles } from "@common/roles";
+import {
+  SigDetailRecord,
+  SigMemberRecord,
+  SigMemberUpdateRecord,
+} from "@common/types/siglead.js";
+import { getTimeInFormat } from "@common/utils";
+import { orgIds2Name } from "@common/orgs";
+
+export const ViewSigLeadPage: React.FC = () => {
+  const navigate = useNavigate();
+  const api = useApi("core");
+  const { colorScheme } = useMantineColorScheme();
+  const { sigId } = useParams();
+  const [sigMembers, setSigMembers] = useState<SigMemberRecord[]>([]);
+  const [sigDetails, setSigDetails] = useState<SigDetailRecord>({
+    sigid: sigId || "",
+    signame: "Default Sig",
+    description:
+      "A cool Sig with a lot of money and members. Founded in 1999 by Sir Charlie of Edinburgh. Focuses on making money and helping others earn more money via education.",
+  });
+
+  useEffect(() => {
+    // Fetch sig data and populate form
+    const getSig = async () => {
+      try {
+        /*const formValues = { 
+          };
+          form.setValues(formValues);*/
+        const sigMemberRequest = await api.get(
+          `/api/v1/siglead/sigmembers/${sigId}`,
+        );
+        setSigMembers(sigMemberRequest.data);
+
+        const sigDetailRequest = await api.get(
+          `/api/v1/siglead/sigdetail/${sigId}`,
+        );
+        setSigDetails(sigDetailRequest.data);
+      } catch (error) {
+        console.error("Error fetching sig data:", error);
+        notifications.show({
+          message: "Failed to fetch sig data, please try again.",
+        });
+      }
+    };
+    getSig();
+  }, [sigId]);
+
+  const renderSigMember = (member: SigMemberRecord, index: number) => {
+    const shouldShow = true;
+    return (
+      <Transition
+        mounted={shouldShow}
+        transition="fade"
+        duration={10000}
+        timingFunction="ease"
+      >
+        {(styles) => (
+          <tr
+            style={{
+              ...styles,
+              display: shouldShow ? "table-row" : "none",
+              backgroundColor:
+                colorScheme === "dark"
+                  ? index % 2 === 0
+                    ? "#333333"
+                    : "#444444"
+                  : index % 2 === 0
+                    ? "#f0f8ff"
+                    : "#ffffff",
+            }}
+          >
+            <Table.Td>{member.memberName}</Table.Td>
+            <Table.Td>{member.email}</Table.Td>
+            <Table.Td>{member.designation}</Table.Td>
+          </tr>
+        )}
+      </Transition>
+    );
+  };
+
+  /*
+    const form = useForm<EventPostRequest>({
+      validate: zodResolver(requestBodySchema),
+      initialValues: {
+        title: '',
+        description: '',
+        start: new Date(),
+        end: new Date(new Date().valueOf() + 3.6e6), // 1 hr later
+        location: 'ACM Room (Siebel CS 1104)',
+        locationLink: 'https://maps.app.goo.gl/dwbBBBkfjkgj8gvA8',
+        host: 'ACM',
+        featured: false,
+        repeats: undefined,
+        repeatEnds: undefined,
+        paidEventId: undefined,
+      },
+    });
+    /*
+    const handleSubmit = async (values: EventPostRequest) => {
+      try {
+        setIsSubmitting(true);
+        const realValues = {
+          ...values,
+          start: dayjs(values.start).format('YYYY-MM-DD[T]HH:mm:00'),
+          end: values.end ? dayjs(values.end).format('YYYY-MM-DD[T]HH:mm:00') : undefined,
+          repeatEnds:
+            values.repeatEnds && values.repeats
+              ? dayjs(values.repeatEnds).format('YYYY-MM-DD[T]HH:mm:00')
+              : undefined,
+          repeats: values.repeats ? values.repeats : undefined,
+        };
+  
+        const eventURL = isEditing ? `/api/v1/events/${eventId}` : '/api/v1/events';
+        const response = await api.post(eventURL, realValues);
+        notifications.show({
+          title: isEditing ? 'Event updated!' : 'Event created!',
+          message: isEditing ? undefined : `The event ID is "${response.data.id}".`,
+        });
+        navigate('/events/manage');
+      } catch (error) {
+        setIsSubmitting(false);
+        console.error('Error creating/editing event:', error);
+        notifications.show({
+          message: 'Failed to create/edit event, please try again.',
+        });
+      }
+    };*/
+
+  return (
+    <AuthGuard
+      resourceDef={{ service: "core", validRoles: [AppRoles.SIGLEAD_MANAGER] }}
+    >
+      <Container>
+        <Group align="flex-start">
+          <Box style={{ flex: 8 }}>
+            <Title order={1}>{sigDetails.signame}</Title>
+            {sigDetails.description || ""}
+          </Box>
+          <Box style={{ flex: 1, textAlign: "right", alignItems: "right" }}>
+            <Stack>
+              <Button variant="white">Member Count: {sigMembers.length}</Button>
+
+              <Button onClick={() => navigate("./addMember")}>
+                Add Member
+              </Button>
+              <Button
+                onClick={() => navigate("../siglead-management")}
+                variant="outline"
+                color="gray"
+              >
+                Back
+              </Button>
+            </Stack>
+          </Box>
+        </Group>
+        <div style={{ width: "100%", overflowX: "auto" }}>
+          <Table style={{ tableLayout: "fixed", width: "100%" }}>
+            <Table.Thead>
+              <Table.Tr>
+                <Table.Th>Name</Table.Th>
+                <Table.Th>Email</Table.Th>
+                <Table.Th>Roles</Table.Th>
+              </Table.Tr>
+            </Table.Thead>
+            <Table.Tbody>
+              {sigMembers.length > 0 ? sigMembers.map(renderSigMember) : <></>}
+            </Table.Tbody>
+          </Table>
+        </div>
+      </Container>
+    </AuthGuard>
+  );
+};
+
+export const AddMemberToSigPage: FC = () => {
+  // const { sigId } = useParams();
+  const api = useApi("core");
+
+  async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
+    event.preventDefault();
+    const formData = new FormData(event.currentTarget);
+    // console.log(formData)
+    const data = Object.fromEntries(formData.entries()) as {
+      groupid: string;
+      aid: string;
+      rid: string;
+    };
+
+    try {
+      const response = await api.patch(`/api/v1/iam/groups/${data.groupid}`, {
+        add: data.aid !== "" ? [data.aid] : [],
+        remove: data.rid !== "" ? [data.rid] : [],
+      });
+
+      console.warn(`GRAPH API RESPONSE: ${response}`);
+      notifications.show({
+        message: JSON.stringify(response),
+      });
+    } catch (error) {
+      notifications.show({
+        message: JSON.stringify(error),
+      });
+    }
+
+    // console.log(response);
+  }
+
+  // async function testAddGroup() {
+  //   await api.patch(
+  //     `/api/v1/iam/groups/:e37a2420-1030-48da-9d17-f7e201b446e1`,
+  //     { add: ["d115c8cb-2520-4ba4-bc36-dd55af69c590"], remove: [] },
+  //   );
+  // }
+
+  return (
+    <AuthGuard
+      resourceDef={{ service: "core", validRoles: [AppRoles.SIGLEAD_MANAGER] }}
+    >
+      <form id="form" onSubmit={handleSubmit}>
+        <label htmlFor="groupid">group id: </label>
+        <input
+          type="text"
+          name="groupid"
+          id="groupid"
+          placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+        />
+        <br />
+        <label htmlFor="id">add uuid: </label>
+        <input
+          type="text"
+          name="aid"
+          id="aid"
+          placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+        />
+        <br />
+        <label htmlFor="id">remove uuid: </label>
+        <input
+          type="text"
+          name="rid"
+          id="rid"
+          placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+        />
+        <br />
+        <button type="submit">Submit</button>
+      </form>
+    </AuthGuard>
+  );
+};
diff --git a/tests/unit/common/utils.test.ts b/tests/unit/common/utils.test.ts
index 15177175..e22d642c 100644
--- a/tests/unit/common/utils.test.ts
+++ b/tests/unit/common/utils.test.ts
@@ -1,5 +1,5 @@
 import { expect, test, describe } from "vitest";
-import { transformCommaSeperatedName } from "../../../src/common/utils.js";
+import { transformCommaSeperatedName, transformSigLeadToURI } from "../../../src/common/utils.js";
 
 describe("Comma-seperated name transformer tests", () => {
   test("Already-transformed names are returned as-is", () => {
@@ -27,3 +27,146 @@ describe("Comma-seperated name transformer tests", () => {
     expect(output).toEqual(", Test");
   });
 });
+
+describe("transformSigLeadToURI tests", () => {
+
+  // Basic Functionality Tests
+  test("should convert simple names with spaces to lowercase hyphenated", () => {
+    const output = transformSigLeadToURI("SIG Network");
+    expect(output).toEqual("sig-network");
+  });
+
+  test("should convert simple names to lowercase", () => {
+    const output = transformSigLeadToURI("Testing");
+    expect(output).toEqual("testing");
+  });
+
+  test("should handle names already in the desired format", () => {
+    const output = transformSigLeadToURI("already-transformed-name");
+    expect(output).toEqual("already-transformed-name");
+  });
+
+  // Camel Case Tests
+  test("should add hyphens between camelCase words", () => {
+    const output = transformSigLeadToURI("SIGAuth");
+    expect(output).toEqual("sig-auth");
+  });
+
+  test("should handle multiple camelCase words", () => {
+    const output = transformSigLeadToURI("SuperCamelCaseProject");
+    expect(output).toEqual("super-camel-case-project");
+  });
+
+  test("should handle mixed camelCase and spaces", () => {
+    const output = transformSigLeadToURI("SIG ContribEx"); // SIG Contributor Experience
+    expect(output).toEqual("sig-contrib-ex");
+  });
+
+  test("should handle camelCase starting with lowercase", () => {
+    const output = transformSigLeadToURI("myCamelCaseName");
+    expect(output).toEqual("my-camel-case-name");
+  });
+
+  // Reserved Character Tests (RFC 3986 gen-delims and sub-delims)
+  test("should convert reserved characters like & to hyphens", () => {
+    const output = transformSigLeadToURI("SIG Storage & Backup");
+    expect(output).toEqual("sig-storage-backup"); // & -> space -> hyphen
+  });
+
+  test("should convert reserved characters like / and : to hyphens", () => {
+    const output = transformSigLeadToURI("Project:Alpha/Beta");
+    expect(output).toEqual("project-alpha-beta"); // : -> space, / -> space, space+space -> hyphen
+  });
+
+  test("should convert reserved characters like () and + to hyphens", () => {
+    const output = transformSigLeadToURI("My Project (Test+Alpha)");
+    expect(output).toEqual("my-project-test-alpha");
+  });
+
+  test("should convert various reserved characters #[]@?$, to hyphens", () => {
+    const output = transformSigLeadToURI("Special#Chars[Test]?@Value,$");
+    expect(output).toEqual("special-chars-test-value");
+  });
+
+  // Non-Allowed Character Removal Tests
+  test("should remove characters not unreserved or reserved (e.g., ™, ©)", () => {
+    const output = transformSigLeadToURI("MyOrg™ With © Symbols");
+    expect(output).toEqual("my-org-with-symbols");
+  });
+
+  test("should remove emoji", () => {
+    const output = transformSigLeadToURI("Project ✨ Fun");
+    expect(output).toEqual("project-fun");
+  });
+
+
+  // Whitespace and Hyphen Collapsing Tests
+  test("should handle multiple spaces between words", () => {
+    const output = transformSigLeadToURI("SIG   UI   Project");
+    expect(output).toEqual("sig-ui-project");
+  });
+
+  test("should handle leading/trailing whitespace", () => {
+    const output = transformSigLeadToURI("  Leading and Trailing  ");
+    expect(output).toEqual("leading-and-trailing");
+  });
+
+  test("should handle mixed whitespace (tabs, newlines)", () => {
+    const output = transformSigLeadToURI("Mix\tOf\nWhite Space");
+    expect(output).toEqual("mix-of-white-space");
+  });
+
+  test("should collapse multiple hyphens resulting from transformations", () => {
+    const output = transformSigLeadToURI("Test--Multiple / Spaces");
+    expect(output).toEqual("test-multiple-spaces");
+  });
+
+  test("should collapse hyphens from start/end after transformations", () => {
+    const output = transformSigLeadToURI("&Another Test!");
+    expect(output).toEqual("another-test");
+  });
+
+  // Unreserved Character Tests (RFC 3986)
+  test("should keep unreserved characters: hyphen, period, underscore, tilde", () => {
+    const output = transformSigLeadToURI("Keep.These-Chars_Okay~123");
+    expect(output).toEqual("keep.these-chars_okay~123");
+  });
+
+  test("should handle unreserved chars next to reserved chars", () => {
+    const output = transformSigLeadToURI("Test._~&Stuff");
+    expect(output).toEqual("test._~-stuff");
+  });
+
+
+  // Edge Case Tests
+  test("should return an empty string for an empty input", () => {
+    const output = transformSigLeadToURI("");
+    expect(output).toEqual("");
+  });
+
+  test("should return an empty string for input with only spaces", () => {
+    const output = transformSigLeadToURI("   ");
+    expect(output).toEqual("");
+  });
+
+  test("should return an empty string for input with only reserved/non-allowed chars and spaces", () => {
+    const output = transformSigLeadToURI("  & / # ™ ©   ");
+    expect(output).toEqual("");
+  });
+
+  test("should handle numbers correctly", () => {
+    const output = transformSigLeadToURI("ProjectApollo11");
+    expect(output).toEqual("project-apollo11"); // Number doesn't trigger camel case break after letter
+  });
+
+  test("should handle numbers triggering camel case break", () => {
+    const output = transformSigLeadToURI("Project11Apollo");
+    expect(output).toEqual("project-11-apollo"); // Letter after number triggers camel case break
+  });
+
+  test("should handle names starting with lowercase", () => {
+    const output = transformSigLeadToURI("myOrg");
+    expect(output).toEqual("my-org");
+  });
+
+});