diff --git a/src/Clients.Admin.Web/Configurations/ApiSettings.cs b/src/Clients.Admin.Web/Configurations/ApiSettings.cs
new file mode 100644
index 0000000..1b9a5eb
--- /dev/null
+++ b/src/Clients.Admin.Web/Configurations/ApiSettings.cs
@@ -0,0 +1,8 @@
+namespace MadWorldNL.MantaRayPlan.Web.Configurations;
+
+public class ApiSettings
+{
+ public const string Key = "Api";
+
+ public string Address { get; set; } = string.Empty;
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Configurations/ApiTypes.cs b/src/Clients.Admin.Web/Configurations/ApiTypes.cs
new file mode 100644
index 0000000..770b053
--- /dev/null
+++ b/src/Clients.Admin.Web/Configurations/ApiTypes.cs
@@ -0,0 +1,6 @@
+namespace MadWorldNL.MantaRayPlan.Web.Configurations;
+
+public static class ApiTypes
+{
+ public const string AdminBff = nameof(AdminBff);
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Pages/MessageBuses/MessageBus.razor b/src/Clients.Admin.Web/Pages/MessageBuses/MessageBus.razor
new file mode 100644
index 0000000..b16bbef
--- /dev/null
+++ b/src/Clients.Admin.Web/Pages/MessageBuses/MessageBus.razor
@@ -0,0 +1,46 @@
+@using MadWorldNL.MantaRayPlan.Events
+@using MadWorldNL.MantaRayPlan.Web.Services.Events
+@using MadWorldNL.MantaRayPlan.Web.Services.MessageBuses
+@page "/MessageBus"
+
+@inject IMessageBusService MessageBusService;
+@inject EventsService EventsService
+
+Message Bus Test Page
+@if (_isLoaded)
+{
+ status counter: @_counter
+
+
+
+}
+
+@code {
+ private bool _isLoaded;
+ private int _counter;
+
+ protected override async Task OnInitializedAsync()
+ {
+ var status = await MessageBusService.GetStatusAsync();
+ _counter = status.counter;
+ _isLoaded = true;
+
+ EventsService.EventReceived += NewEventReceived;
+
+ await EventsService.StartAsync();
+ await base.OnInitializedAsync();
+ }
+
+ private void NewEventReceived(MessageBusStatusEvent @event)
+ {
+ _counter = @event.Count;
+ StateHasChanged();
+ }
+
+ private async Task UpdateStatus()
+ {
+ await MessageBusService.PostNewStatusAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Program.cs b/src/Clients.Admin.Web/Program.cs
index 45f4973..5d3fad4 100644
--- a/src/Clients.Admin.Web/Program.cs
+++ b/src/Clients.Admin.Web/Program.cs
@@ -1,11 +1,27 @@
using MadWorldNL.MantaRayPlan.Web;
+using MadWorldNL.MantaRayPlan.Web.Configurations;
+using MadWorldNL.MantaRayPlan.Web.Services.Events;
+using MadWorldNL.MantaRayPlan.Web.Services.MessageBuses;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
+using Microsoft.Extensions.Options;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add("#app");
builder.RootComponents.Add("head::after");
+builder.Services
+ .AddOptions()
+ .Configure(builder.Configuration.GetSection(ApiSettings.Key).Bind);
+
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
+builder.Services.AddHttpClient(ApiTypes.AdminBff, (serviceProvider, client) =>
+ {
+ var apiUrlsOption = serviceProvider.GetService>()!;
+ client.BaseAddress = new Uri(apiUrlsOption.Value.Address);
+ });
+
+builder.Services.AddScoped();
+builder.Services.AddSingleton();
await builder.Build().RunAsync();
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Services/Events/EventsService.cs b/src/Clients.Admin.Web/Services/Events/EventsService.cs
new file mode 100644
index 0000000..2a5d4da
--- /dev/null
+++ b/src/Clients.Admin.Web/Services/Events/EventsService.cs
@@ -0,0 +1,45 @@
+using MadWorldNL.MantaRayPlan.Events;
+using MadWorldNL.MantaRayPlan.Web.Configurations;
+using Microsoft.AspNetCore.SignalR.Client;
+using Microsoft.Extensions.Options;
+
+namespace MadWorldNL.MantaRayPlan.Web.Services.Events;
+
+public class EventsService : IAsyncDisposable
+{
+ private bool _isStarted;
+ private readonly HubConnection _hubConnection;
+
+ public event Action? EventReceived;
+
+ public EventsService(IOptions settings)
+ {
+ _hubConnection = new HubConnectionBuilder()
+ .WithUrl($"{settings.Value.Address}Events")
+ .Build();
+
+ _hubConnection.On("NewEvent", (@event) =>
+ {
+ EventReceived?.Invoke(@event);
+ });
+ }
+
+ public Task StartAsync()
+ {
+ if (_isStarted)
+ {
+ return Task.CompletedTask;
+ }
+
+ _isStarted = true;
+ return _hubConnection.StartAsync();
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ await _hubConnection.StopAsync();
+ await _hubConnection.DisposeAsync();
+
+ GC.SuppressFinalize(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Services/MessageBuses/IMessageBusService.cs b/src/Clients.Admin.Web/Services/MessageBuses/IMessageBusService.cs
new file mode 100644
index 0000000..17778fc
--- /dev/null
+++ b/src/Clients.Admin.Web/Services/MessageBuses/IMessageBusService.cs
@@ -0,0 +1,9 @@
+using MadWorldNL.MantaRayPlan.MessageBuses;
+
+namespace MadWorldNL.MantaRayPlan.Web.Services.MessageBuses;
+
+public interface IMessageBusService
+{
+ Task GetStatusAsync();
+ Task PostNewStatusAsync();
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/Services/MessageBuses/MessageBusService.cs b/src/Clients.Admin.Web/Services/MessageBuses/MessageBusService.cs
new file mode 100644
index 0000000..02b5563
--- /dev/null
+++ b/src/Clients.Admin.Web/Services/MessageBuses/MessageBusService.cs
@@ -0,0 +1,31 @@
+using System.Net.Http.Json;
+using MadWorldNL.MantaRayPlan.MessageBuses;
+using MadWorldNL.MantaRayPlan.Web.Configurations;
+
+namespace MadWorldNL.MantaRayPlan.Web.Services.MessageBuses;
+
+public class MessageBusService(IHttpClientFactory clientFactory) : IMessageBusService
+{
+ private const string EndpointSingular = "MessageBus";
+
+ private readonly HttpClient _client = clientFactory.CreateClient(ApiTypes.AdminBff);
+
+ public async Task GetStatusAsync()
+ {
+ const int emptyCounter = -1;
+
+ return await _client.GetFromJsonAsync($"{EndpointSingular}/Status") ?? new GetStatusResponse("No response", emptyCounter);
+ }
+
+ public async Task PostNewStatusAsync()
+ {
+ var response = await _client.PostAsJsonAsync($"{EndpointSingular}/Status", "{}");
+
+ if (response.IsSuccessStatusCode)
+ {
+ return await response.Content.ReadFromJsonAsync() ?? new PostStatusResponse("No Response");
+ }
+
+ return new PostStatusResponse("IsFailedStatusCode");
+ }
+}
\ No newline at end of file
diff --git a/src/Clients.Admin.Web/wwwroot/appsettings.json b/src/Clients.Admin.Web/wwwroot/appsettings.json
new file mode 100644
index 0000000..23d6c3c
--- /dev/null
+++ b/src/Clients.Admin.Web/wwwroot/appsettings.json
@@ -0,0 +1,5 @@
+{
+ "Api": {
+ "Address": "https://localhost:7284/"
+ }
+}
\ No newline at end of file
diff --git a/src/Clients.Viewer.Bff.IntegrationTests/Base/SharedTestCollection.cs b/src/Clients.Viewer.Bff.IntegrationTests/Base/SharedTestCollection.cs
new file mode 100644
index 0000000..bd6e772
--- /dev/null
+++ b/src/Clients.Viewer.Bff.IntegrationTests/Base/SharedTestCollection.cs
@@ -0,0 +1,6 @@
+namespace MadWorldNL.MantaRayPlan.Base;
+
+[CollectionDefinition(TestDefinitions.Default)]
+public class SharedTestCollection : ICollectionFixture
+{
+}
\ No newline at end of file
diff --git a/src/Clients.Viewer.Bff.IntegrationTests/Base/ViewerBffFactory.cs b/src/Clients.Viewer.Bff.IntegrationTests/Base/ViewerBffFactory.cs
new file mode 100644
index 0000000..05bf91e
--- /dev/null
+++ b/src/Clients.Viewer.Bff.IntegrationTests/Base/ViewerBffFactory.cs
@@ -0,0 +1,61 @@
+using MassTransit;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Testcontainers.RabbitMq;
+
+namespace MadWorldNL.MantaRayPlan.Base;
+
+public class ViewerBffFactory : WebApplicationFactory, IAsyncLifetime
+{
+ private const string BusUser = "development";
+ private const string BusPassword = "Password1234";
+
+ private RabbitMqContainer? _rabbitMqContainer;
+
+ public async Task InitializeAsync()
+ {
+ _rabbitMqContainer = new RabbitMqBuilder()
+ .WithImage("rabbitmq:3.11")
+ .WithUsername(BusUser)
+ .WithPassword(BusPassword)
+ .Build();
+
+ await _rabbitMqContainer.StartAsync();
+ }
+
+ protected override IHost CreateHost(IHostBuilder builder)
+ {
+ var newSettings = new Dictionary
+ {
+ ["MessageBus:Host"] = _rabbitMqContainer!.Hostname,
+ ["MessageBus:Port"] = _rabbitMqContainer.GetMappedPublicPort(5672).ToString(),
+ ["MessageBus:Username"] = BusUser,
+ ["MessageBus:Password"] = BusPassword
+ };
+
+ builder.ConfigureHostConfiguration(config =>
+ {
+ config.AddInMemoryCollection(newSettings!);
+ });
+
+ builder.ConfigureServices(services =>
+ {
+ // For more info about testing message bus:
+ // https://masstransit.io/documentation/concepts/testing
+ //services.AddMassTransitTestHarness();
+ });
+
+ return base.CreateHost(builder);
+ }
+
+ public new async Task DisposeAsync()
+ {
+ if (_rabbitMqContainer is not null)
+ {
+ await _rabbitMqContainer.DisposeAsync();
+ }
+
+ await base.DisposeAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/Clients.Viewer.Bff.IntegrationTests/Clients.Viewer.Bff.IntegrationTests.csproj b/src/Clients.Viewer.Bff.IntegrationTests/Clients.Viewer.Bff.IntegrationTests.csproj
index 4d7dbde..1c18fb9 100644
--- a/src/Clients.Viewer.Bff.IntegrationTests/Clients.Viewer.Bff.IntegrationTests.csproj
+++ b/src/Clients.Viewer.Bff.IntegrationTests/Clients.Viewer.Bff.IntegrationTests.csproj
@@ -13,6 +13,7 @@
+
@@ -23,6 +24,7 @@