diff --git a/frontend/index.html b/frontend/index.html
index 4dd5611..0f400a0 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -7,6 +7,7 @@
+
RemoteTerm for MeshCore
diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/frontend/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 878f6c8..99e075d 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,4 +1,13 @@
-import { useState, useEffect, useCallback, useMemo, useRef, startTransition } from 'react';
+import {
+ useState,
+ useEffect,
+ useCallback,
+ useMemo,
+ useRef,
+ startTransition,
+ lazy,
+ Suspense,
+} from 'react';
import { api } from './api';
import { useWebSocket } from './useWebSocket';
import {
@@ -20,9 +29,13 @@ import {
type SettingsSection,
} from './components/SettingsModal';
import { RawPacketList } from './components/RawPacketList';
-import { MapView } from './components/MapView';
-import { VisualizerView } from './components/VisualizerView';
import { CrackerPanel } from './components/CrackerPanel';
+
+// Lazy-load heavy components (Leaflet, force-directed graph) to reduce initial bundle
+const MapView = lazy(() => import('./components/MapView').then((m) => ({ default: m.MapView })));
+const VisualizerView = lazy(() =>
+ import('./components/VisualizerView').then((m) => ({ default: m.VisualizerView }))
+);
import { Sheet, SheetContent, SheetHeader, SheetTitle } from './components/ui/sheet';
import { Toaster, toast } from './components/ui/sonner';
import {
@@ -947,7 +960,7 @@ export function App() {
-
+
{activeConversation ? (
activeConversation.type === 'map' ? (
@@ -956,16 +969,32 @@ export function App() {
Node Map
-
+
+ Loading map...
+
+ }
+ >
+
+
>
) : activeConversation.type === 'visualizer' ? (
- setRawPackets([])}
- />
+
+ Loading visualizer...
+
+ }
+ >
+ setRawPackets([])}
+ />
+
) : activeConversation.type === 'raw' ? (
<>
@@ -1208,7 +1237,7 @@ export function App() {
)}
-
+
{/* Global Cracker Panel - always rendered to maintain state */}
diff --git a/frontend/src/components/CrackerPanel.tsx b/frontend/src/components/CrackerPanel.tsx
index 400c7a1..7d43546 100644
--- a/frontend/src/components/CrackerPanel.tsx
+++ b/frontend/src/components/CrackerPanel.tsx
@@ -455,8 +455,11 @@ export function CrackerPanel({