diff --git a/packages/frontend/app/components/Notifications/Notification.tsx b/packages/frontend/app/components/Notifications/Notification.tsx
index 66131cca0..00842aab2 100644
--- a/packages/frontend/app/components/Notifications/Notification.tsx
+++ b/packages/frontend/app/components/Notifications/Notification.tsx
@@ -9,6 +9,7 @@ import { useAppSettings } from '~/stores/AppSettingsStore';
import type { notificationIF } from '~/stores/NotificationStore';
import styles from './Notification.module.css';
import { t } from 'i18next';
+import { FaDev } from 'react-icons/fa6';
interface propsIF {
data: notificationIF;
@@ -198,6 +199,9 @@ export default function Notification(props: propsIF) {
color='var(--red)'
/>
)}
+ {data.icon === 'console' && (
+
+ )}
{
+ const { default: Component } = await import(
+ './routes/status/Status'
+ );
+ return { Component };
+ },
+ },
{
path: 'v2/terms',
lazy: async () => {
diff --git a/packages/frontend/app/routes/status/Status.module.css b/packages/frontend/app/routes/status/Status.module.css
new file mode 100644
index 000000000..2c620265d
--- /dev/null
+++ b/packages/frontend/app/routes/status/Status.module.css
@@ -0,0 +1,145 @@
+.container {
+ padding: var(--padding-l);
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: var(--margin-l);
+}
+
+.title {
+ font-size: var(--font-size-l);
+ color: var(--text1);
+ margin: 0;
+}
+
+.refresh {
+ background: var(--accent1);
+ color: var(--text1);
+ border: none;
+ padding: var(--padding-s) var(--padding-m);
+ border-radius: var(--radius-xs);
+ font-size: var(--font-size-s);
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.refresh:hover {
+ background: var(--accent1-dark);
+}
+
+.report_section {
+ background: var(--bg-dark2);
+ border: 1px solid var(--bg-dark4);
+ border-radius: var(--radius-s);
+ padding: var(--padding-m);
+ margin-bottom: var(--margin-l);
+}
+
+.report_title {
+ font-size: var(--font-size-m);
+ color: var(--text1);
+ margin: 0 0 var(--margin-m) 0;
+}
+
+.reports_list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap-s);
+}
+
+.report_item {
+ background: var(--bg-dark3);
+ border: 1px solid var(--bg-dark5);
+ border-radius: var(--radius-xs);
+ padding: var(--padding-m);
+}
+
+.report_message {
+ color: var(--text1);
+ font-size: var(--font-size-s);
+ margin-bottom: var(--margin-s);
+ white-space: pre-wrap;
+ word-break: break-word;
+ line-height: 1.5;
+}
+
+.report_timestamp {
+ color: var(--text3);
+ font-size: var(--font-size-xs);
+ font-family: var(--font-family-mono);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: var(--gap-m);
+}
+
+.card {
+ background: var(--bg-dark2);
+ border: 1px solid var(--bg-dark4);
+ border-radius: var(--radius-s);
+ padding: var(--padding-m);
+ transition: all 0.3s ease;
+}
+
+.card:hover {
+ background: var(--bg-dark3);
+}
+
+.card_title {
+ font-size: var(--font-size-m);
+ color: var(--text1);
+ margin-bottom: var(--margin-s);
+}
+
+.card_status {
+ font-size: var(--font-size-s);
+ font-weight: 600;
+ margin-bottom: var(--margin-xs);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.card_time {
+ font-size: var(--font-size-s);
+ color: var(--text2);
+ margin-bottom: var(--margin-s);
+ font-family: var(--font-family-mono);
+}
+
+.card_url {
+ font-size: var(--font-size-xs);
+ color: var(--text3);
+ word-break: break-all;
+ font-family: var(--font-family-mono);
+}
+
+.status_operational {
+ border-color: var(--green);
+}
+
+.status_operational .card_status {
+ color: var(--green);
+}
+
+.status_down {
+ border-color: var(--red);
+}
+
+.status_down .card_status {
+ color: var(--red);
+}
+
+.status_checking {
+ border-color: var(--accent4);
+}
+
+.status_checking .card_status {
+ color: var(--accent4);
+}
diff --git a/packages/frontend/app/routes/status/Status.tsx b/packages/frontend/app/routes/status/Status.tsx
new file mode 100644
index 000000000..e46b8b693
--- /dev/null
+++ b/packages/frontend/app/routes/status/Status.tsx
@@ -0,0 +1,180 @@
+import { useEffect, useState, type ReactElement } from 'react';
+import styles from './Status.module.css';
+import {
+ POLLING_API_INFO_ENDPOINT,
+ MARKET_INFO_ENDPOINT,
+ RPC_ENDPOINT,
+ blockExplorer,
+} from '~/utils/Constants';
+
+type EndpointStatus = {
+ name: string;
+ url: string;
+ status: 'checking' | 'operational' | 'down';
+ responseTime?: number;
+ lastChecked?: Date;
+};
+
+type StatusReport = {
+ id: string;
+ message: string;
+ timestamp: Date;
+};
+
+const ENDPOINTS = [
+ { name: 'Polling API', url: POLLING_API_INFO_ENDPOINT },
+ { name: 'Market API', url: MARKET_INFO_ENDPOINT },
+ { name: 'RPC Endpoint', url: RPC_ENDPOINT },
+ { name: 'Block Explorer', url: blockExplorer },
+ {
+ name: 'Ember',
+ url: 'https://ember-leaderboard-v2.liquidity.tools/health',
+ },
+];
+
+export default function Status(): ReactElement {
+ const [endpoints, setEndpoints] = useState(
+ ENDPOINTS.map((ep) => ({ ...ep, status: 'checking' as const })),
+ );
+ const [statusReports, setStatusReports] = useState([
+ {
+ id: '1',
+ message:
+ 'All systems operational. Successfully processed 1.2M transactions in the last 24 hours.',
+ timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
+ },
+ {
+ id: '2',
+ message:
+ 'Scheduled maintenance completed. API response times improved by 15%.',
+ timestamp: new Date(Date.now() - 8 * 60 * 60 * 1000), // 8 hours ago
+ },
+ {
+ id: '3',
+ message:
+ 'Investigating intermittent connectivity issues with RPC endpoint. Updates to follow.',
+ timestamp: new Date(Date.now() - 24 * 60 * 60 * 1000), // 1 day ago
+ },
+ ]);
+
+ const checkEndpoint = async (
+ endpoint: EndpointStatus,
+ ): Promise => {
+ const startTime = performance.now();
+
+ try {
+ await fetch(endpoint.url, {
+ method: 'HEAD',
+ mode: 'no-cors',
+ });
+
+ const endTime = performance.now();
+ const responseTime = Math.round(endTime - startTime);
+
+ return {
+ ...endpoint,
+ status: 'operational',
+ responseTime,
+ lastChecked: new Date(),
+ };
+ } catch (error) {
+ const endTime = performance.now();
+ const responseTime = Math.round(endTime - startTime);
+
+ return {
+ ...endpoint,
+ status: 'down',
+ responseTime,
+ lastChecked: new Date(),
+ };
+ }
+ };
+
+ const checkAllEndpoints = async (): Promise => {
+ setEndpoints((prev) =>
+ prev.map((ep) => ({ ...ep, status: 'checking' as const })),
+ );
+
+ const updatedEndpoints = await Promise.all(
+ endpoints.map(checkEndpoint),
+ );
+
+ setEndpoints(updatedEndpoints);
+ };
+
+ const fetchStatusReports = async (): Promise => {
+ // TODO: Replace with actual API call to fetch status reports
+ // const response = await fetch('/api/status-reports');
+ // const data = await response.json();
+ // setStatusReports(data);
+ };
+
+ useEffect(() => {
+ checkAllEndpoints();
+ fetchStatusReports();
+ }, []);
+
+ const getStatusColor = (status: EndpointStatus['status']): string => {
+ switch (status) {
+ case 'operational':
+ return styles.status_operational;
+ case 'down':
+ return styles.status_down;
+ case 'checking':
+ return styles.status_checking;
+ }
+ };
+
+ return (
+
+
+
System Status
+
+
+
+ {statusReports.length > 0 && (
+
+
Status Updates
+
+ {statusReports.map((report) => (
+
+
+ {report.message}
+
+
+ {report.timestamp.toLocaleString()}
+
+
+ ))}
+
+
+ )}
+
+
+ {endpoints.map((endpoint) => (
+
+
{endpoint.name}
+
+ {endpoint.status === 'checking'
+ ? 'Checking...'
+ : endpoint.status === 'operational'
+ ? 'Operational'
+ : 'Down'}
+
+ {endpoint.responseTime !== undefined && (
+
+ {endpoint.responseTime}ms
+
+ )}
+
{endpoint.url}
+
+ ))}
+
+
+ );
+}
diff --git a/packages/frontend/app/stores/NotificationStore.ts b/packages/frontend/app/stores/NotificationStore.ts
index f4e4d1b61..ac17ac7cd 100644
--- a/packages/frontend/app/stores/NotificationStore.ts
+++ b/packages/frontend/app/stores/NotificationStore.ts
@@ -1,7 +1,7 @@
import { create } from 'zustand';
// slugs to indicate which React icon should be rendered
-type icons = 'spinner' | 'check' | 'error';
+type icons = 'spinner' | 'check' | 'error' | 'console';
// shape of post-processed data used to construct a DOM element
export interface notificationIF {