diff --git a/packages/dashboard/examples/demo/app.css b/packages/dashboard/examples/demo/app.css
new file mode 100644
index 000000000..2319b13e4
--- /dev/null
+++ b/packages/dashboard/examples/demo/app.css
@@ -0,0 +1,8 @@
+html,
+body,
+#root {
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+}
diff --git a/packages/dashboard/examples/demo/index.html b/packages/dashboard/examples/demo/index.html
new file mode 100644
index 000000000..f13043862
--- /dev/null
+++ b/packages/dashboard/examples/demo/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ RMF Dashboard
+
+
+
+
+
+
diff --git a/packages/dashboard/examples/demo/index.tsx b/packages/dashboard/examples/demo/index.tsx
new file mode 100644
index 000000000..1324d9cc5
--- /dev/null
+++ b/packages/dashboard/examples/demo/index.tsx
@@ -0,0 +1,115 @@
+import '@fontsource/roboto/300.css';
+import '@fontsource/roboto/400.css';
+import '@fontsource/roboto/500.css';
+import '@fontsource/roboto/700.css';
+import './app.css';
+
+import ReactDOM from 'react-dom/client';
+import {
+ InitialWindow,
+ LocallyPersistentWorkspace,
+ RmfDashboard,
+ Workspace,
+} from 'rmf-dashboard/components';
+import { MicroAppManifest } from 'rmf-dashboard/components/micro-app';
+import doorsApp from 'rmf-dashboard/micro-apps/doors-app';
+import liftsApp from 'rmf-dashboard/micro-apps/lifts-app';
+import createMapApp from 'rmf-dashboard/micro-apps/map-app';
+import robotMutexGroupsApp from 'rmf-dashboard/micro-apps/robot-mutex-groups-app';
+import robotsApp from 'rmf-dashboard/micro-apps/robots-app';
+import tasksApp from 'rmf-dashboard/micro-apps/tasks-app';
+import StubAuthenticator from 'rmf-dashboard/services/stub-authenticator';
+
+const mapApp = createMapApp({
+ attributionPrefix: 'Open-RMF',
+ defaultMapLevel: 'L1',
+ defaultRobotZoom: 20,
+ defaultZoom: 6,
+});
+
+const appRegistry: MicroAppManifest[] = [
+ mapApp,
+ doorsApp,
+ liftsApp,
+ robotsApp,
+ robotMutexGroupsApp,
+ tasksApp,
+];
+
+const homeWorkspace: InitialWindow[] = [
+ {
+ layout: { x: 0, y: 0, w: 12, h: 6 },
+ microApp: mapApp,
+ },
+];
+
+const robotsWorkspace: InitialWindow[] = [
+ {
+ layout: { x: 0, y: 0, w: 7, h: 4 },
+ microApp: robotsApp,
+ },
+ { layout: { x: 8, y: 0, w: 5, h: 8 }, microApp: mapApp },
+ { layout: { x: 0, y: 0, w: 7, h: 4 }, microApp: doorsApp },
+ { layout: { x: 0, y: 0, w: 7, h: 4 }, microApp: liftsApp },
+ { layout: { x: 8, y: 0, w: 5, h: 4 }, microApp: robotMutexGroupsApp },
+];
+
+const tasksWorkspace: InitialWindow[] = [
+ { layout: { x: 0, y: 0, w: 7, h: 8 }, microApp: tasksApp },
+ { layout: { x: 8, y: 0, w: 5, h: 8 }, microApp: mapApp },
+];
+
+export default function App() {
+ return (
+ ,
+ },
+ {
+ name: 'Robots',
+ route: 'robots',
+ element: ,
+ },
+ {
+ name: 'Tasks',
+ route: 'tasks',
+ element: ,
+ },
+ {
+ name: 'Custom',
+ route: 'custom',
+ element: (
+
+ ),
+ },
+ ]}
+ />
+ );
+}
+
+const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
+root.render();
diff --git a/packages/dashboard/examples/demo/public/favicon.ico b/packages/dashboard/examples/demo/public/favicon.ico
new file mode 100644
index 000000000..6c149bf7f
Binary files /dev/null and b/packages/dashboard/examples/demo/public/favicon.ico differ
diff --git a/packages/dashboard/examples/demo/public/resources/defaultLogo.png b/packages/dashboard/examples/demo/public/resources/defaultLogo.png
new file mode 100644
index 000000000..06ce6c02a
Binary files /dev/null and b/packages/dashboard/examples/demo/public/resources/defaultLogo.png differ
diff --git a/packages/dashboard/examples/demo/public/robots.txt b/packages/dashboard/examples/demo/public/robots.txt
new file mode 100644
index 000000000..01b0f9a10
--- /dev/null
+++ b/packages/dashboard/examples/demo/public/robots.txt
@@ -0,0 +1,2 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
diff --git a/packages/dashboard/examples/demo/public/silent-check-sso.html b/packages/dashboard/examples/demo/public/silent-check-sso.html
new file mode 100644
index 000000000..20ad2098d
--- /dev/null
+++ b/packages/dashboard/examples/demo/public/silent-check-sso.html
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/dashboard/examples/demo/vite.config.ts b/packages/dashboard/examples/demo/vite.config.ts
new file mode 100644
index 000000000..f637d65d7
--- /dev/null
+++ b/packages/dashboard/examples/demo/vite.config.ts
@@ -0,0 +1,13 @@
+import react from '@vitejs/plugin-react-swc';
+import path from 'path';
+import { defineConfig } from 'vite';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ 'rmf-dashboard': path.resolve(__dirname, '../../src'),
+ },
+ },
+});
diff --git a/packages/dashboard/tsconfig.app.json b/packages/dashboard/tsconfig.app.json
index 1babef830..e61d21a5b 100644
--- a/packages/dashboard/tsconfig.app.json
+++ b/packages/dashboard/tsconfig.app.json
@@ -21,7 +21,11 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+
+ "paths": {
+ "rmf-dashboard/*": ["./src/*"]
+ }
},
- "include": ["src", "app-config.json"]
+ "include": ["src", "examples", "app-config.json"]
}