diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9feacfd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,36 @@
+*.swp
+*.*~
+project.lock.json
+.DS_Store
+*.pyc
+nupkg/
+
+# Visual Studio Code
+
+# Rider
+.idea
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+msbuild.log
+msbuild.err
+msbuild.wrn
+
+# Visual Studio 2015
+.vs/
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..14a9546
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,27 @@
+{
+  "version": "0.2.0",
+  "configurations": [
+    {
+      // Use IntelliSense to find out which attributes exist for C# debugging
+      // Use hover for the description of the existing attributes
+      // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
+      "name": ".NET Core Launch (console)",
+      "type": "coreclr",
+      "request": "launch",
+      "preLaunchTask": "build",
+      // If you have changed target frameworks, make sure to update the program path.
+      "program": "${workspaceFolder}/AuroraCradle/bin/Debug/netcoreapp3.1/aurora-cradle-sharp.dll",
+      "args": [],
+      "cwd": "${workspaceFolder}",
+      // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+      "console": "internalConsole",
+      "stopAtEntry": false
+    },
+    {
+      "name": ".NET Core Attach",
+      "type": "coreclr",
+      "request": "attach",
+      "processId": "${command:pickProcess}"
+    }
+  ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..736a20a
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,42 @@
+{
+  "version": "2.0.0",
+  "tasks": [
+    {
+      "label": "build",
+      "command": "dotnet",
+      "type": "process",
+      "args": [
+        "build",
+        "${workspaceFolder}/AuroraCradle/aurora-cradle-sharp.csproj",
+        "/property:GenerateFullPaths=true",
+        "/consoleloggerparameters:NoSummary"
+      ],
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "publish",
+      "command": "dotnet",
+      "type": "process",
+      "args": [
+        "publish",
+        "${workspaceFolder}/aurora-cradle-sharp.csproj",
+        "/property:GenerateFullPaths=true",
+        "/consoleloggerparameters:NoSummary"
+      ],
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "watch",
+      "command": "dotnet",
+      "type": "process",
+      "args": [
+        "watch",
+        "run",
+        "${workspaceFolder}/aurora-cradle-sharp.csproj",
+        "/property:GenerateFullPaths=true",
+        "/consoleloggerparameters:NoSummary"
+      ],
+      "problemMatcher": "$msCompile"
+    }
+  ]
+}
diff --git a/AuroraCradle.test/AuroraSignal.test.csproj b/AuroraCradle.test/AuroraSignal.test.csproj
new file mode 100644
index 0000000..8aa4944
--- /dev/null
+++ b/AuroraCradle.test/AuroraSignal.test.csproj
@@ -0,0 +1,27 @@
+
+
+  
+    net5.0
+
+    false
+  
+
+  
+    
+    
+    
+    
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+      all
+    
+    
+      runtime; build; native; contentfiles; analyzers; buildtransitive
+      all
+    
+  
+
+  
+    
+  
+
+
diff --git a/AuroraCradle.test/CursorList.test.cs b/AuroraCradle.test/CursorList.test.cs
new file mode 100644
index 0000000..4a99d96
--- /dev/null
+++ b/AuroraCradle.test/CursorList.test.cs
@@ -0,0 +1,163 @@
+using Xunit;
+using Aurora.Services.Signal;
+using Aurora.Cursor;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AuroraCradle.test
+{
+    public class CursorListTest
+    {
+        [Theory()]
+        [InlineData(Aurora.Cursor.SortDirection.Asc)]
+        [InlineData(Aurora.Cursor.SortDirection.Desc)]
+        public void CursorListSortOnStringValue(Aurora.Cursor.SortDirection direction)
+        {
+            CursorList list = new CursorList();
+            list.Add(new Party() { Name = "asdf", Id = Faker.RandomNumber.Next().ToString() });
+            list.Add(new Party() { Name = "bsdf", Id = Faker.RandomNumber.Next().ToString() });
+            list.Add(new Party() { Name = "csdf", Id = Faker.RandomNumber.Next().ToString() });
+
+            CursorResult result = new Cursor(ref list)
+                .WithSort(item => item.Value.Name, direction)
+                .GetNextPage();
+
+            if (direction == Aurora.Cursor.SortDirection.Desc)
+            {
+                Assert.Collection(result.Result,
+                    item => item.Name.Equals("asdf"),
+                    item => item.Name.Equals("bsdf"),
+                    item => item.Name.Equals("csdf"));
+            }
+            else
+            {
+                Assert.Collection(result.Result,
+                    item => item.Name.Equals("csdf"),
+                    item => item.Name.Equals("bsdf"),
+                    item => item.Name.Equals("asdf"));
+
+            }
+        }
+
+        [Theory()]
+        [InlineData(2)]
+        [InlineData(10)]
+        [InlineData(49)]
+        [InlineData(51)]
+        [InlineData(-1)]
+        public void CursorListSizeTest(int size)
+        {
+            int numOfItems = 50;
+            CursorList list = new CursorList();
+
+            // Add items to cursor list
+            for (int i = 0; i < numOfItems; i++)
+            {
+                list.Add(new Party()
+                {
+                    Name = string.Join(" ",
+                    Faker.Lorem.Words(2)),
+                    Id = Faker.RandomNumber.Next().ToString()
+                });
+            }
+
+            Cursor cursor = new Cursor(ref list);
+            if (size < 0)
+            {
+                Assert.Throws(() =>
+                {
+                    cursor.WithSize(size).GetNextPage();
+                });
+            }
+            else if (size > numOfItems)
+            {
+                CursorResult res = cursor.WithSize(size).GetNextPage();
+                Assert.Equal(res.Result.Count, numOfItems);
+            }
+            else if (size < numOfItems && size > 0)
+            {
+                CursorResult res = cursor.WithSize(size).GetNextPage();
+                Assert.Equal(res.Result.Count, size);
+            }
+        }
+
+        [Theory()]
+        [InlineData(2)]
+        [InlineData(10)]
+        [InlineData(3)]
+        public void CursorPaginationTest(int pageSize)
+        {
+            int numOfItems = 50;
+            CursorList list = new CursorList();
+
+            // Add items to cursor list
+            for (int i = 0; i < numOfItems; i++)
+            {
+                list.Add(new Party()
+                {
+                    Name = string.Join(" ",
+                    Faker.Lorem.Words(2)),
+                    Id = Faker.RandomNumber.Next().ToString()
+                });
+            }
+
+            string pageToken = null;
+            Cursor cursor = new Cursor(ref list);
+            List pagedResults = new List();
+            while (pageToken != string.Empty)
+            {
+                CursorResult res = cursor
+                    .WithSize(pageSize)
+                    .WithNextPageToken(pageToken)
+                    .GetNextPage();
+
+                pagedResults.AddRange(res.Result);
+                pageToken = res.NextPageToken;
+            }
+
+            Assert.Equal(pagedResults.Count, numOfItems);
+        }
+
+        [Fact()]
+
+        public void CursorPaginationWithSortTest()
+        {
+            int numOfItems = 50;
+            CursorList cursorList = new CursorList();
+
+            // Add items to cursor list
+            for (int i = 0; i < numOfItems; i++)
+            {
+                cursorList.Add(new Party()
+                {
+                    Name = string.Join(" ",
+                    Faker.Lorem.Words(2)),
+                    Id = Faker.RandomNumber.Next().ToString()
+                });
+            }
+
+            var orderedList = cursorList.ToList().OrderBy(item => item.Value.Name).ToList().ConvertAll(item => item.Value);
+
+            string pageToken = null;
+            Cursor cursor = new Cursor(ref cursorList);
+            List pagedResults = new List();
+            while (pageToken != string.Empty)
+            {
+                CursorResult res = cursor
+                    .WithSize(10)
+                    .WithSort(item => item.Value.Name, Aurora.Cursor.SortDirection.Asc)
+                    .WithNextPageToken(pageToken)
+                    .GetNextPage();
+
+                pagedResults.AddRange(res.Result);
+                pageToken = res.NextPageToken;
+            }
+
+            var list = cursorList.ToList();
+            for (int i = 0; i < orderedList.Count; i++)
+            {
+                Assert.Equal(orderedList[i], pagedResults[i]);
+            }
+        }
+    }
+}
diff --git a/AuroraCradle/Src/Augments/Party.cs b/AuroraCradle/Src/Augments/Party.cs
new file mode 100644
index 0000000..52c697f
--- /dev/null
+++ b/AuroraCradle/Src/Augments/Party.cs
@@ -0,0 +1,9 @@
+using Aurora.Cursor;
+
+namespace Aurora.Services.Signal
+{
+    public partial class Party : ICursorObject
+    {
+    }
+}
+
diff --git a/AuroraCradle/Src/Cursor/Cursor.cs b/AuroraCradle/Src/Cursor/Cursor.cs
new file mode 100644
index 0000000..9a60991
--- /dev/null
+++ b/AuroraCradle/Src/Cursor/Cursor.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+#nullable enable
+namespace Aurora.Cursor
+{
+    public enum SortDirection
+    {
+        Asc,
+        Desc,
+    }
+
+    public class Cursor where T : ICursorObject
+    {
+        private CursorList _list;
+
+        private string? _previousPageToken;
+        private string? _nextPageToken;
+        private int _pageSize;
+        private Func, string> _sortDelgate;
+        private SortDirection _direction;
+        public Cursor(ref CursorList list)
+        {
+            this._list = list;
+            this._previousPageToken = string.Empty;
+            this._nextPageToken = string.Empty;
+            this._pageSize = 10;
+            this._sortDelgate = delegate (KeyValuePair item)
+            {
+                return item.Key;
+            };
+        }
+
+        public CursorResult GetNextPage()
+        {
+            if (this._pageSize < 0)
+            {
+                throw new InvalidOperationException("Page Size must be greater than zero");
+            }
+            List> tmpList;
+
+            // Sort reference list
+            if (this._direction == SortDirection.Desc)
+            {
+                tmpList = this._list.OrderByDescending(this._sortDelgate).ToList();
+
+            }
+            else
+            {
+                tmpList = this._list.OrderBy(this._sortDelgate).ToList();
+            }
+
+            if (tmpList == null)
+            {
+                throw new System.NullReferenceException();
+            }
+
+            int startIdx = 0;
+            if (!string.IsNullOrEmpty(this._nextPageToken))
+            {
+                // TODO find another way to index into the list that's not a regular array search
+                startIdx = tmpList.FindIndex(item => item.Key == this._nextPageToken) + 1;
+            }
+
+            int adjustedSize = this._pageSize;
+            if (startIdx + this._pageSize > tmpList.Count)
+            {
+                adjustedSize = this._pageSize - ((startIdx + _pageSize) - tmpList.Count);
+            }
+
+
+            List> selection = new List>();
+            if (adjustedSize != 0)
+            {
+                selection = tmpList.GetRange(startIdx, adjustedSize);
+            }
+
+            return new CursorResult
+            {
+                NextPageToken = this._pageSize == selection.Count ? selection[selection.Count - 1].Key : string.Empty,
+                PrevPageToken = string.Empty,
+                Count = this._list.Count,
+                Result = selection.ConvertAll(item => item.Value)
+            };
+        }
+
+        public CursorResult GetPreviousPage()
+        {
+            throw new NotImplementedException();
+        }
+
+        public Cursor WithNextPageToken(string nextPageToken)
+        {
+            this._nextPageToken = nextPageToken;
+            return this;
+        }
+
+        public Cursor WithPreviousPageToken(string prevPageToken)
+        {
+            this._previousPageToken = prevPageToken;
+            return this;
+        }
+
+        public Cursor WithSort(Func, string> sortDelegate, SortDirection direction)
+        {
+            this._sortDelgate = sortDelegate;
+            this._direction = direction;
+            return this;
+        }
+
+        public Cursor WithSort(string key, SortDirection direction)
+        {
+            this._sortDelgate = (item) => key;
+            this._direction = direction;
+            return this;
+        }
+
+        public Cursor WithSize(int size)
+        {
+            this._pageSize = size;
+            return this;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/AuroraCradle/Src/Cursor/CursorList.cs b/AuroraCradle/Src/Cursor/CursorList.cs
new file mode 100644
index 0000000..0dcbf04
--- /dev/null
+++ b/AuroraCradle/Src/Cursor/CursorList.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using System.Collections;
+using System;
+using System.Linq;
+using Aurora.Utils;
+
+#nullable enable
+namespace Aurora.Cursor
+{
+
+    public class CursorList : SortedList where T : ICursorObject
+    {
+
+        public CursorList()
+        {
+        }
+
+        public CursorList Add(T item)
+        {
+            string id = item.Id;
+            if (item.Id == null)
+            {
+                id = HashUtil.GetHash(new string[] { item.GetHashCode().ToString() }).ToString();
+                item.Id = id;
+            }
+            bool res = this.TryAdd(id, item);
+
+            if (res == false)
+            {
+                throw new System.Exception("Failed to add item to cursor list");
+            }
+            return this;
+        }
+
+
+    }
+}
\ No newline at end of file
diff --git a/AuroraCradle/Src/Cursor/CursorObject.cs b/AuroraCradle/Src/Cursor/CursorObject.cs
new file mode 100644
index 0000000..cca1779
--- /dev/null
+++ b/AuroraCradle/Src/Cursor/CursorObject.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Aurora.Cursor
+{
+    public interface ICursorObject
+    {
+        string Id { get; set; }
+    }
+}
diff --git a/AuroraCradle/Src/Cursor/CursorResult.cs b/AuroraCradle/Src/Cursor/CursorResult.cs
new file mode 100644
index 0000000..ab50c6a
--- /dev/null
+++ b/AuroraCradle/Src/Cursor/CursorResult.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Aurora.Cursor
+{
+    public class CursorResult
+    {
+        public CursorResult()
+        {
+            Result = new List();
+        }
+
+        public CursorResult(CursorResult cpy)
+        {
+            NextPageToken = cpy.NextPageToken;
+            PrevPageToken = cpy.PrevPageToken;
+            Result = cpy.Result;
+            Count = cpy.Count;
+        }
+
+        public string NextPageToken { get; set; }
+        public string PrevPageToken { get; set; }
+        public List Result { get; set; }
+        public int Count { get; set; }
+    }
+}
diff --git a/AuroraCradle/Src/Program.cs b/AuroraCradle/Src/Program.cs
new file mode 100644
index 0000000..6ffeaba
--- /dev/null
+++ b/AuroraCradle/Src/Program.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+
+namespace Aurora
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            CreateHostBuilder(args).Build().Run();
+        }
+
+        // Additional configuration is required to successfully run gRPC on macOS.
+        // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
+        public static IHostBuilder CreateHostBuilder(string[] args) =>
+            Host.CreateDefaultBuilder(args)
+                .ConfigureWebHostDefaults(webBuilder =>
+                {
+                    webBuilder.UseStartup();
+                });
+    }
+}
diff --git a/AuroraCradle/Src/Protos/signal.proto b/AuroraCradle/Src/Protos/signal.proto
new file mode 100644
index 0000000..078630d
--- /dev/null
+++ b/AuroraCradle/Src/Protos/signal.proto
@@ -0,0 +1,167 @@
+syntax = "proto3";
+
+option csharp_namespace = "Aurora.Services.Signal";
+
+package signal;
+
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/empty.proto";
+
+
+service Signal {
+    //**************
+    //Party Resource
+    //**************
+    //Get Party
+    rpc ListParties(ListPartiesRequest) returns (ListPartiesResponse);
+
+    rpc GetParty(GetPartyRequest) returns (Party);
+
+    rpc UpdateParty(UpdatePartyRequest) returns (Party);
+
+    rpc CreateParty(CreatePartyRequest) returns (Party);
+
+    rpc DeleteParty(DeletePartyRequest) returns (google.protobuf.Empty);
+
+
+    //***************************
+    //EventSubscriptions Resource
+    //***************************
+    //List
+    rpc ListEventSubscriptions(ListEventSubscriptionsRequest) returns (ListEventSubscriptionsResponse);
+
+    //Create
+    rpc SubscribeToEvent(EventSubscriptionRequest) returns (EventSubscription);
+    
+    //Delete
+    rpc DeleteEventSubscription(DeleteEventSubscriptionRequest) returns (google.protobuf.Empty);
+
+    //CUSTOM: Create EventSubscription List
+    rpc SubscribeToEvents(EventSubscriptionListRequest) returns (EventSubscriptionListResponse);
+
+    //CUSTOM: Delete all
+    rpc DeleteAllEventSubscriptions(DeleteAllEventSubscriptionsRequest) returns (google.protobuf.Empty);
+    
+    //*****
+    //Event 
+    //*****
+    //Get
+    rpc GetEventStream(GetEventsRequest) returns (stream BaseEvent) {};
+}
+
+message Party {
+    //The resource name of the party
+    string name = 1;
+    string id = 2;
+    string display_name = 3;
+    string description = 4;
+    string host_ip = 5;
+    google.protobuf.Timestamp created_on = 6;
+}
+
+message PartyListItem {
+    string name = 1;
+    string id = 2;
+}
+
+message ListPartiesRequest {
+    int32 page_size = 1;
+    string page_token = 2;
+    string order_by = 3;
+    SortDirection order_direction = 4;
+}
+
+enum SortDirection {
+    Asc = 0;
+    Desc = 1;
+}
+
+message ListPartiesResponse {
+    repeated PartyListItem parties = 1;
+    string next_page_token = 2;
+}
+
+message GetPartyRequest {
+    string party_id = 1;
+}
+
+message CreatePartyRequest {
+    string party_id = 1;
+    Party party = 2;
+}
+
+message DeletePartyRequest {
+    string party_id = 1;
+}
+
+message UpdatePartyRequest {
+    Party party = 1;
+    google.protobuf.FieldMask update_mask = 2;
+}
+
+/* Event Types */
+enum EventType {
+    NewPartiesAvailable = 0;
+}
+
+message NewPartiesAvailableEvent {
+}
+
+message BaseEvent {
+    //Resource name of the event ?
+    string name = 1;
+    EventType event_type = 2;    
+    oneof derivedEvent {
+        NewPartiesAvailableEvent new_parties_available_event = 3;
+    }
+}
+
+message EventSubscription {
+    EventType type = 2;
+}
+
+message ListEventSubscriptionsRequest {
+    //Resource name of parent to the subscription list (The member)
+    string parent = 1;
+    int32 page_size = 2;
+    string page_token = 3;
+}
+
+message ListEventSubscriptionsResponse {
+    repeated EventSubscription subscriptions = 1;
+    string next_page_token = 2;
+}
+
+message EventSubscriptionRequest {
+    //Resource name of the parent to the subscription list (The member)
+    string parent = 1;
+    EventSubscription event_subscription = 2;
+}
+
+message DeleteEventSubscriptionRequest {
+    //Resource name of the subscription to delete
+    string parent = 1;
+    EventType type = 2;
+}
+
+message EventSubscriptionListRequest {
+    //Resource name of the parent to the subscription list (The member)
+    string parent = 1;
+    repeated EventSubscription event_subscriptions = 2;
+}
+
+message EventSubscriptionListResponse {
+    repeated EventSubscription event_subscriptions = 1;
+}
+
+message DeleteAllEventSubscriptionsRequest {
+    //Resource name of the parent to the subscription list (the member)
+    string parent = 1;
+}
+
+message GetEventsRequest {
+    //Resource name of the parent to the event stream (the member)
+    string parent = 1;
+}
diff --git a/AuroraCradle/Src/Services/Signal/Events.cs b/AuroraCradle/Src/Services/Signal/Events.cs
new file mode 100644
index 0000000..41e7034
--- /dev/null
+++ b/AuroraCradle/Src/Services/Signal/Events.cs
@@ -0,0 +1,7 @@
+namespace Aurora.Services.Signal
+{
+    public partial class SignalService : Signal.SignalBase
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/AuroraCradle/Src/Services/Signal/Party.cs b/AuroraCradle/Src/Services/Signal/Party.cs
new file mode 100644
index 0000000..c044cde
--- /dev/null
+++ b/AuroraCradle/Src/Services/Signal/Party.cs
@@ -0,0 +1,79 @@
+using System.Threading.Tasks;
+using Google.Protobuf.WellKnownTypes;
+using Grpc.Core;
+using Aurora.Cursor;
+using Microsoft.Extensions.Logging;
+
+namespace Aurora.Services.Signal
+{
+    public partial class SignalService : Signal.SignalBase
+    {
+        private CursorList _partyList;
+
+        public override Task CreateParty(CreatePartyRequest request, ServerCallContext context)
+        {
+            Party party = new Party(request.Party);
+            _partyList.Add(party);
+
+            this._logger.LogInformation(string.Format("Added party with name: ${0} to parties", party.Name));
+
+            return Task.FromResult(party);
+        }
+
+        public override Task DeleteParty(DeletePartyRequest request, ServerCallContext context)
+        {
+            if (this._partyList.ContainsKey(request.PartyId))
+            {
+                this._partyList.Remove(request.PartyId);
+            }
+
+            this._logger.LogInformation(string.Format("Deleted party with id: ${0} to parties", request.PartyId));
+            return Task.FromResult(new Empty());
+        }
+
+        public override Task ListParties(ListPartiesRequest request, ServerCallContext context)
+        {
+            Cursor cursor = new Cursor(ref this._partyList);
+
+            Aurora.Cursor.SortDirection direction = Aurora.Cursor.SortDirection.Asc;
+            if (request.OrderDirection == SortDirection.Desc)
+            {
+                direction = Aurora.Cursor.SortDirection.Desc;
+            }
+
+            CursorResult res = cursor
+                .WithSort(request.OrderBy, direction)
+                .WithNextPageToken(request.PageToken)
+                .WithSize(request.PageSize)
+                .GetNextPage();
+
+            ListPartiesResponse response = new ListPartiesResponse()
+            {
+                NextPageToken = res.NextPageToken
+            };
+            response.Parties.AddRange(res.Result.ConvertAll(party => new PartyListItem()
+            {
+                Name = party.Name,
+                Id = party.Id
+            }));
+            return Task.FromResult(response);
+        }
+
+        public override Task GetParty(GetPartyRequest request, ServerCallContext context)
+        {
+            Party party = new Party();
+
+            if (this._partyList.ContainsKey(request.PartyId))
+            {
+                this._partyList.TryGetValue(request.PartyId, out party);
+            }
+
+            return Task.FromResult(party);
+        }
+
+        public override Task UpdateParty(UpdatePartyRequest request, ServerCallContext context)
+        {
+            throw new System.NotImplementedException();
+        }
+    }
+}
\ No newline at end of file
diff --git a/AuroraCradle/Src/Services/Signal/SignalService.cs b/AuroraCradle/Src/Services/Signal/SignalService.cs
new file mode 100644
index 0000000..3561c59
--- /dev/null
+++ b/AuroraCradle/Src/Services/Signal/SignalService.cs
@@ -0,0 +1,17 @@
+using Microsoft.Extensions.Logging;
+using Aurora.Cursor;
+
+namespace Aurora.Services.Signal
+{
+    public partial class SignalService : Signal.SignalBase
+    {
+        private readonly ILogger _logger;
+
+        public SignalService(ILogger logger)
+        {
+            _logger = logger;
+            this._partyList = new CursorList();
+        }
+
+    }
+}
diff --git a/AuroraCradle/Src/Startup.cs b/AuroraCradle/Src/Startup.cs
new file mode 100644
index 0000000..57b8520
--- /dev/null
+++ b/AuroraCradle/Src/Startup.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Aurora.Services.Signal;
+
+namespace Aurora
+{
+    public class Startup
+    {
+        // This method gets called by the runtime. Use this method to add services to the container.
+        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddGrpc();
+            services.AddGrpcReflection();
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+
+            }
+
+            app.UseRouting();
+
+            app.UseEndpoints(endpoints =>
+            {
+                endpoints.MapGrpcService();
+
+                if (env.IsDevelopment())
+                {
+                    endpoints.MapGrpcReflectionService();
+                }
+                endpoints.MapGet("/", async context =>
+                {
+                    await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
+                });
+            });
+        }
+    }
+}
diff --git a/AuroraCradle/Src/Utils/HashUtil.cs b/AuroraCradle/Src/Utils/HashUtil.cs
new file mode 100644
index 0000000..0644870
--- /dev/null
+++ b/AuroraCradle/Src/Utils/HashUtil.cs
@@ -0,0 +1,25 @@
+using System.Security.Cryptography;
+using System.Text;
+using System;
+
+namespace Aurora.Utils
+{
+    public class HashUtil
+    {
+        public static Guid GetHash(string[] inputs)
+        {
+            string input = "";
+            foreach (string str in inputs)
+            {
+                input += str;
+            }
+
+            byte[] stringbytes = Encoding.UTF8.GetBytes(input);
+            byte[] hashedBytes = new System.Security.Cryptography
+                .SHA1CryptoServiceProvider()
+                .ComputeHash(stringbytes);
+            Array.Resize(ref hashedBytes, 16);
+            return new Guid(hashedBytes);
+        }
+    }
+}
diff --git a/AuroraCradle/appsettings.Development.json b/AuroraCradle/appsettings.Development.json
new file mode 100644
index 0000000..fe20c40
--- /dev/null
+++ b/AuroraCradle/appsettings.Development.json
@@ -0,0 +1,10 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Debug",
+      "System": "Information",
+      "Grpc": "Information",
+      "Microsoft": "Information"
+    }
+  }
+}
diff --git a/AuroraCradle/appsettings.json b/AuroraCradle/appsettings.json
new file mode 100644
index 0000000..df549a7
--- /dev/null
+++ b/AuroraCradle/appsettings.json
@@ -0,0 +1,15 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    }
+  },
+  "AllowedHosts": "*",
+  "Kestrel": {
+    "EndpointDefaults": {
+      "Protocols": "Http1"
+    }
+  }
+}
diff --git a/AuroraCradle/aurora-cradle-sharp.csproj b/AuroraCradle/aurora-cradle-sharp.csproj
new file mode 100644
index 0000000..1e350d2
--- /dev/null
+++ b/AuroraCradle/aurora-cradle-sharp.csproj
@@ -0,0 +1,16 @@
+
+
+  
+    netcoreapp3.1
+  
+
+  
+    
+  
+
+  
+    
+    
+  
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e230517
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# aurora-cradle-sharp
+
diff --git a/workspace.code-workspace b/workspace.code-workspace
new file mode 100644
index 0000000..1e373c0
--- /dev/null
+++ b/workspace.code-workspace
@@ -0,0 +1,15 @@
+{
+  "folders": [
+    {
+      "path": "."
+    }
+  ],
+"settings": {
+    "files.exclude": {
+        "**/obj": true
+    },
+    "dotnet-test-explorer.testProjectPath": "./AuroraCradle.test",
+    "editor.formatOnSave": true,
+    "editor.defaultFormatter": "ms-dotnettools.csharp"
+}
+}