diff --git a/apps/ui/src/lib/common.ts b/apps/ui/src/lib/common.ts
index c67a88929..9ed667f43 100644
--- a/apps/ui/src/lib/common.ts
+++ b/apps/ui/src/lib/common.ts
@@ -3,6 +3,8 @@ import { addToast } from '$lib/store';
export const asyncSleep = (delay: number) =>
new Promise((resolve) => setTimeout(resolve, delay));
+export let initials = (str:string) => (str||'').split(' ').map( (wrd) => wrd[0]).join('')
+
export function errorNotification(error: any | { message: string }): void {
if (error.message) {
if (error.message === 'Cannot read properties of undefined (reading \'postMessage\')') {
@@ -87,4 +89,4 @@ export function handlerNotFoundLoad(error: any, url: URL) {
export function getRndInteger(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1)) + min;
-}
\ No newline at end of file
+}
diff --git a/apps/ui/src/lib/components/badges/DestinationBadge.svelte b/apps/ui/src/lib/components/badges/DestinationBadge.svelte
new file mode 100644
index 000000000..e9f3fe7ed
--- /dev/null
+++ b/apps/ui/src/lib/components/badges/DestinationBadge.svelte
@@ -0,0 +1,15 @@
+
+
+{#if (name||'').length > 0}
+
+ {initials(name)}
+
+ {name}
+{/if}
\ No newline at end of file
diff --git a/apps/ui/src/lib/components/badges/PublicBadge.svelte b/apps/ui/src/lib/components/badges/PublicBadge.svelte
new file mode 100644
index 000000000..7ce01a074
--- /dev/null
+++ b/apps/ui/src/lib/components/badges/PublicBadge.svelte
@@ -0,0 +1,19 @@
+
\ No newline at end of file
diff --git a/apps/ui/src/lib/components/badges/StatusBadge.svelte b/apps/ui/src/lib/components/badges/StatusBadge.svelte
new file mode 100644
index 000000000..9b386a859
--- /dev/null
+++ b/apps/ui/src/lib/components/badges/StatusBadge.svelte
@@ -0,0 +1,25 @@
+
+{#await getting}
+ ...
+{:then status}
+
+ {status}
+
+{/await}
diff --git a/apps/ui/src/lib/components/badges/TeamsBadge.svelte b/apps/ui/src/lib/components/badges/TeamsBadge.svelte
new file mode 100644
index 000000000..a02078f3e
--- /dev/null
+++ b/apps/ui/src/lib/components/badges/TeamsBadge.svelte
@@ -0,0 +1,17 @@
+
+
+
+ 🏢
+ {#each teams as team}
+
+ {initials(team.name)}
+
+ {team.name}
+ {/each}
+
\ No newline at end of file
diff --git a/apps/ui/src/lib/container/status.ts b/apps/ui/src/lib/container/status.ts
new file mode 100644
index 000000000..f520554a0
--- /dev/null
+++ b/apps/ui/src/lib/container/status.ts
@@ -0,0 +1,73 @@
+//
+// Maps Container ID x Operation Status
+//
+// Example response of $status => {'123asdf': 'degraded', '124asdf': 'running'}
+
+import { writable, get as getStore } from 'svelte/store';
+import { get } from '$lib/api';
+
+export let containerStatus = writable({});
+
+let PERMITED_STATUS = ['loading', 'running', 'healthy', 'building', 'degraded', 'stopped', 'error'];
+
+// refreshStatus([{id}])
+export async function refreshStatus(list:Array) {
+ for (const item of list) {
+ setStatus(item.id, 'loading');
+ getStatus(item, true);
+ }
+}
+
+export async function getStatus(resource: any, force: boolean = false) {
+ const { id, buildPack, dualCerts, engine } = resource;
+ let newStatus = 'stopped';
+
+ // Already set and we're not forcing
+ if (getStore(containerStatus)[id] && !force) return getStore(containerStatus)[id];
+
+ try {
+ if (buildPack) { // Application
+ const response = await get(`/applications/${id}/status`);
+ newStatus = parseApplicationsResponse(response);
+ } else if (typeof dualCerts !== 'undefined') { // Service
+ const response = await get(`/services/${id}/status`);
+ newStatus = parseServiceResponse(response);
+ } else if (typeof engine !== 'undefined'){ // Destination/Server
+ const response = await get(`/destinations/${id}/status`);
+ newStatus = response.isRunning ? 'running' : 'stopped';
+ } else { // Database
+ const response = await get(`/databases/${id}/status`);
+ newStatus = response.isRunning ? 'running' : 'stopped';
+ }
+ } catch (error) {
+ newStatus = 'error';
+ }
+
+ setStatus(id, newStatus);
+ // console.log("GOT:", id, newStatus)
+ return newStatus
+}
+
+const setStatus = (thingId, newStatus) => {
+ if(!PERMITED_STATUS.includes(newStatus))
+ throw(`Change to ${newStatus} is not permitted. Try: ${PERMITED_STATUS.join(', ')}`);
+ containerStatus.update(n => Object.assign(n, {thingId: newStatus}));
+};
+
+// -- Response Parsing
+
+function parseApplicationsResponse(list:Array){
+ if (list.length === 0) return 'stopped';
+ if (list.length === 1) return list[0].status.isRunning ? 'running' : 'stopped';
+ return allWorking(list.map( (el:any) => el.status.isRunning ))
+}
+
+function parseServiceResponse(response:any){
+ if (Object.keys(response).length === 0) return 'stopped';
+ let list = Object.keys(response).map((el) => el.status.isRunning)
+ return allWorking(list) ? 'running' : 'degraded'
+}
+
+function allWorking(list:Array){
+ return list.reduce((acum:boolean,res:boolean) => acum && res) ? 'running' : 'degraded';
+}