diff --git a/Emergence.api/Emergence.api.csproj b/Emergence.api/Emergence.api.csproj
new file mode 100644
index 0000000..e00a355
--- /dev/null
+++ b/Emergence.api/Emergence.api.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Emergence.api/Emergence.api.http b/Emergence.api/Emergence.api.http
new file mode 100644
index 0000000..20f1a6b
--- /dev/null
+++ b/Emergence.api/Emergence.api.http
@@ -0,0 +1,11 @@
+@Emergence.api_HostAddress = http://localhost:5235
+
+GET {{Emergence.api_HostAddress}}/users/
+Accept: application/json
+###
+GET {{Emergence.api_HostAddress}}/users/2
+Accept: application/json
+###
+GET {{Emergence.api_HostAddress}}/openapi/emergence.yaml
+Accept: application/json
+###
\ No newline at end of file
diff --git a/Emergence.api/Endpoints/UserEndpoints.cs b/Emergence.api/Endpoints/UserEndpoints.cs
new file mode 100644
index 0000000..a92ed08
--- /dev/null
+++ b/Emergence.api/Endpoints/UserEndpoints.cs
@@ -0,0 +1,30 @@
+using Emergence.api.Interfaces;
+using Emergence.models;
+using Emergence.services.Interface;
+using Microsoft.AspNetCore.Http.HttpResults;
+
+namespace Emergence.api.Endpoints;
+
+public class UserEndpoints : IEndpoint
+{
+ private readonly IUserService _userService;
+
+ public UserEndpoints(IUserService userService)
+ {
+ _userService = userService;
+ }
+
+ public void MapEndPoint(IEndpointRouteBuilder app)
+ {
+ var endpoints = app.MapGroup("/users")
+ .WithTags("User Items");
+
+ endpoints.MapGet("/", GetAll).Produces>(StatusCodes.Status200OK).Produces(StatusCodes.Status404NotFound).WithName("Get All Users");
+ endpoints.MapGet("/{id}", GetById).Produces(StatusCodes.Status200OK).Produces(StatusCodes.Status404NotFound).WithName("Get User By Id");
+ }
+
+ public async Task>, NotFound>> GetAll() =>
+ await _userService.GetAllAsync() is List result ? TypedResults.Ok(result) : TypedResults.NotFound();
+ public async Task, NotFound>> GetById(int id) =>
+ await _userService.GetByIdAsync(id) is UserModel result ? TypedResults.Ok(result) : TypedResults.NotFound();
+}
diff --git a/Emergence.api/Extensions/EndpointExtension.cs b/Emergence.api/Extensions/EndpointExtension.cs
new file mode 100644
index 0000000..714ddc5
--- /dev/null
+++ b/Emergence.api/Extensions/EndpointExtension.cs
@@ -0,0 +1,39 @@
+using Emergence.api.Interfaces;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System.Reflection;
+
+namespace Emergence.api.Extensions;
+
+public static class EndpointExtension
+{
+ public static IServiceCollection AddEndpoints(this IServiceCollection services, Assembly assembly)
+ {
+ // Find all classes that implement IEndpoint and register them for DI
+ ServiceDescriptor[] serviceDescriptors = assembly
+ .DefinedTypes
+ .Where(type => type is { IsAbstract: false, IsInterface: false } &&
+ type.IsAssignableTo(typeof(IEndpoint)))
+ .Select(type => ServiceDescriptor.Transient(typeof(IEndpoint), type))
+ .ToArray();
+
+ services.TryAddEnumerable(serviceDescriptors);
+
+ return services;
+ }
+
+ public static IApplicationBuilder MapEndpoints(this WebApplication app, RouteGroupBuilder? routeGroupBuilder = null)
+ {
+ IEnumerable endpoints = app.Services
+ .GetRequiredService>();
+
+ IEndpointRouteBuilder builder =
+ routeGroupBuilder is null ? app : routeGroupBuilder;
+
+ foreach (IEndpoint endpoint in endpoints)
+ {
+ endpoint.MapEndPoint(builder);
+ }
+
+ return app;
+ }
+}
diff --git a/Emergence.api/Interfaces/IEndpoint.cs b/Emergence.api/Interfaces/IEndpoint.cs
new file mode 100644
index 0000000..4584542
--- /dev/null
+++ b/Emergence.api/Interfaces/IEndpoint.cs
@@ -0,0 +1,7 @@
+namespace Emergence.api.Interfaces
+{
+ public interface IEndpoint
+ {
+ void MapEndPoint(IEndpointRouteBuilder app);
+ }
+}
diff --git a/Emergence.api/Program.cs b/Emergence.api/Program.cs
new file mode 100644
index 0000000..ae644fc
--- /dev/null
+++ b/Emergence.api/Program.cs
@@ -0,0 +1,22 @@
+using Emergence.api.Extensions;
+using Emergence.services.Extensions;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
+builder.Services.AddOpenApi();
+builder.Services.AddServices();
+builder.Services.AddEndpoints(typeof(Program).Assembly);
+
+var app = builder.Build();
+
+
+app.UseHttpsRedirection();
+app.MapEndpoints();
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.MapOpenApi("/openapi/emergence.yaml");
+}
+app.Run();
diff --git a/Emergence.api/Properties/launchSettings.json b/Emergence.api/Properties/launchSettings.json
new file mode 100644
index 0000000..9d92552
--- /dev/null
+++ b/Emergence.api/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "http://localhost:5235",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "https://localhost:7228;http://localhost:5235",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/Emergence.api/appsettings.Development.json b/Emergence.api/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/Emergence.api/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/Emergence.api/appsettings.json b/Emergence.api/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/Emergence.api/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/Emergence.models/Emergence.models.csproj b/Emergence.models/Emergence.models.csproj
new file mode 100644
index 0000000..b760144
--- /dev/null
+++ b/Emergence.models/Emergence.models.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
diff --git a/Emergence.models/UserModel.cs b/Emergence.models/UserModel.cs
new file mode 100644
index 0000000..bdfec25
--- /dev/null
+++ b/Emergence.models/UserModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Emergence.models
+{
+ public class UserModel
+ {
+ public int Id { get; set; }
+ public string Username { get; set; }
+ public string Email { get; set; }
+ }
+}
diff --git a/Emergence.services/Emergence.services.csproj b/Emergence.services/Emergence.services.csproj
new file mode 100644
index 0000000..ede46b0
--- /dev/null
+++ b/Emergence.services/Emergence.services.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Emergence.services/Extensions/ServiceBuilderExtension.cs b/Emergence.services/Extensions/ServiceBuilderExtension.cs
new file mode 100644
index 0000000..cbc68ff
--- /dev/null
+++ b/Emergence.services/Extensions/ServiceBuilderExtension.cs
@@ -0,0 +1,19 @@
+using Emergence.services.Interface;
+using Emergence.services.Services;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Emergence.services.Extensions
+{
+ public static class ServiceBuilderExtension
+ {
+ public static IServiceCollection AddServices(this IServiceCollection services)
+ {
+ services = services.AddTransient();
+
+ return services;
+ }
+ }
+}
diff --git a/Emergence.services/Interface/IService.cs b/Emergence.services/Interface/IService.cs
new file mode 100644
index 0000000..a59ffb4
--- /dev/null
+++ b/Emergence.services/Interface/IService.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Emergence.services.Interface
+{
+ public interface IService where T : class
+ {
+ public Task> GetAllAsync();
+ public Task GetByIdAsync(int id);
+ }
+}
diff --git a/Emergence.services/Interface/IUserService.cs b/Emergence.services/Interface/IUserService.cs
new file mode 100644
index 0000000..da13160
--- /dev/null
+++ b/Emergence.services/Interface/IUserService.cs
@@ -0,0 +1,11 @@
+using Emergence.models;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Emergence.services.Interface
+{
+ public interface IUserService : IService
+ {
+ }
+}
diff --git a/Emergence.services/Services/UserService.cs b/Emergence.services/Services/UserService.cs
new file mode 100644
index 0000000..a5a1a71
--- /dev/null
+++ b/Emergence.services/Services/UserService.cs
@@ -0,0 +1,26 @@
+using Emergence.models;
+using Emergence.services.Interface;
+
+namespace Emergence.services.Services;
+
+public class UserService : IUserService
+{
+ private List testList = [
+ new UserModel {Id = 1, Username = "chris", Email ="chris@fjp.com.au" },
+ new UserModel {Id = 2, Username = "kim", Email ="kim@fjp.com.au" },
+ new UserModel {Id = 3, Username = "amanda", Email ="amanda@fjp.com.au" },
+ new UserModel {Id = 4, Username = "reception", Email ="reception@fjp.com.au" },
+ ];
+
+ public async Task> GetAllAsync()
+ {
+ return testList;
+ }
+
+ public async Task GetByIdAsync(int id)
+ {
+#pragma warning disable CS8603 // Possible null reference return.
+ return testList.FirstOrDefault(f => f.Id == id);
+#pragma warning restore CS8603 // Possible null reference return.
+ }
+}
diff --git a/Emergence.slnx b/Emergence.slnx
new file mode 100644
index 0000000..3469523
--- /dev/null
+++ b/Emergence.slnx
@@ -0,0 +1,5 @@
+
+
+
+
+