Skip to main content
MQTT Explorer is built with a clear separation of concerns across three main packages: frontend (app), backend models (backend), and platform bindings (src).

High-Level Architecture

Core Components

Frontend (app/)

React components, Redux state management, Material-UI theming, and user interactions

Backend (backend/)

MQTT topic tree model, message storage, data transformations, and business logic

Platform (src/)

Electron bindings for desktop app and Express server for browser mode

MQTT.js

Connection management, protocol handling, and broker communication

Package Structure

App Package (app/)

The React frontend containing all rendering logic:
app/
├── src/
│   ├── components/        # React components
│   │   ├── Sidebar/       # Topic tree, details, charts
│   │   ├── ConnectionWizard/
│   │   ├── Chart/         # Data visualization
│   │   └── Tree/          # MQTT topic tree
│   ├── actions/           # Redux actions
│   │   ├── ConnectionManager.ts
│   │   └── Settings.ts
│   ├── reducers/          # Redux reducers
│   │   ├── Connection.ts
│   │   └── Tree.ts
│   ├── services/          # Business logic
│   │   ├── llmService.ts  # AI assistant integration
│   │   └── decoders/      # Message format decoders
│   ├── theme.ts           # Material-UI theme
│   ├── store.ts           # Redux store configuration
│   └── index.tsx          # Application entry point
├── webpack.config.js      # Electron build config
├── webpack.browser.config.mjs  # Browser build config
└── package.json
Key files:
  • app/src/components/Sidebar/DetailsTab.tsx - Main UI container (422 lines)
  • app/src/components/Tree/Tree.tsx - Topic tree visualization
  • app/src/theme.ts - Material-UI v7 theme configuration

Backend Package (backend/)

Data models and core business logic:
backend/
├── src/
│   ├── Model/             # Core data models
│   │   ├── Tree.ts        # MQTT topic tree structure
│   │   ├── TreeNode.ts    # Individual topic node
│   │   └── Message.ts     # Message representation
│   ├── DataSource/        # Connection management
│   │   └── MqttSource.ts  # MQTT client wrapper
│   ├── JsonAstParser.ts   # JSON parsing for display
│   └── index.ts           # Public API
└── spec/                  # Backend tests
The backend is framework-agnostic - it doesn’t depend on React or Electron. This enables reuse across platforms.

Platform Layer (src/)

Electron and server bindings:
src/
├── electron.ts            # Electron main process
├── server.ts              # Express + Socket.IO server
├── AuthManager.ts         # Browser mode authentication
├── MenuTemplate.ts        # Electron menu bar
└── spec/                  # UI automation tests
    ├── ui-tests.spec.ts   # Playwright tests
    ├── demoVideo.js       # Documentation video generation
    └── testMcpIntrospection.js  # MCP protocol tests

Data Flow

Desktop Mode (Electron)

Browser Mode (Server)

Browser mode uses Socket.IO for bidirectional communication between client and server. Authentication is handled by AuthManager.ts with bcrypt password hashing.

State Management

Redux Store Structure

interface AppState {
  connection: {
    connected: boolean
    brokerUrl: string
    client?: MqttClient
  }
  tree: {
    rootNode: TreeNode
    selectedNode?: TreeNode
  }
  settings: {
    theme: 'light' | 'dark'
    // ...
  }
}
Locations:
  • Store configuration: app/src/store.ts
  • Reducers: app/src/reducers/
  • Actions: app/src/actions/

MQTT Topic Tree Model

The core data structure (backend/src/Model/Tree.ts):
class TreeNode {
  name: string              // Topic segment name
  path(): string            // Full topic path
  message?: Message         // Latest message
  children: Map<string, TreeNode>  // Child nodes
  
  // Computed properties
  messageCount(): number
  hasChildren(): boolean
  isLeaf(): boolean
}
Key operations:
  • Tree.updateWithMessage() - Insert/update message in tree
  • TreeNode.findNode() - Traverse to specific topic
  • TreeNode.deleteNode() - Remove topic and children
The tree structure is optimized for millions of topics with efficient lookup using Map instead of arrays.

Component Architecture

Main UI Components

App (index.tsx)
└── ConnectionWizard
    └── Form + Validation
└── MainLayout
    ├── Sidebar (Split Pane)
    │   ├── Tree
    │   │   └── TreeNode (recursive)
    │   └── DetailsTab
    │       ├── TopicInfo
    │       ├── MessageValue
    │       ├── Chart
    │       └── AIAssistant  [NEW]
    └── PublishPanel
        └── Editor (ACE)

Component Communication

1

User Interaction

User clicks a topic in the tree
2

Redux Action

selectNode(node) action dispatched
3

State Update

Reducer updates tree.selectedNode
4

Re-render

Connected components re-render with new props

Key Design Patterns

1. Singleton Pattern - LLM Service

Ensures a single instance manages AI assistant state:
// app/src/services/llmService.ts
let llmServiceInstance: LLMService | null = null

export function getLLMService(): LLMService {
  if (!llmServiceInstance) {
    llmServiceInstance = new LLMService()
  }
  return llmServiceInstance
}
See app/src/services/llmService.ts:229 for implementation.

2. Higher-Order Components - Styling

Material-UI’s withStyles HOC for component styling:
import { withStyles } from '@mui/styles'
import { Theme } from '@mui/material/styles'

const styles = (theme: Theme) => ({
  root: {
    backgroundColor: theme.palette.background.default,
    padding: theme.spacing(2),
  },
})

export default withStyles(styles)(MyComponent)
See Styling Guide for conventions.

3. Observer Pattern - Event Bus

Cross-component communication without Redux:
// app/src/eventBus.ts
class EventBus {
  on(event: string, callback: Function): void
  emit(event: string, data?: any): void
}

// Usage
eventBus.on('message:received', handleMessage)
eventBus.emit('message:received', message)

4. Strategy Pattern - Message Decoders

Pluggable decoders for different message formats:
// app/src/decoders/
interface Decoder {
  decode(buffer: Buffer): any
  canDecode(topic: string): boolean
}

class JsonDecoder implements Decoder { /* ... */ }
class ProtobufDecoder implements Decoder { /* ... */ }
class SparkplugDecoder implements Decoder { /* ... */ }

Technology Stack

Frontend

TechnologyVersionPurpose
React19.2.3UI framework
Redux5.0.1State management
Material-UI7.3.6Component library
TypeScript5.9.3Type safety
D3.js7.9.0Data visualization
@visx/*3.xChart components
ACE Editor1.4.11Code editing

Backend

TechnologyVersionPurpose
MQTT.js5.14.1MQTT protocol
Electron39.2.7Desktop platform
Express5.2.1Web server
Socket.IO4.8.1Real-time communication
Protobuf.js8.0.0Binary message decoding

Development

TechnologyVersionPurpose
Webpack5.98.0Module bundling
Mocha10.8.2Test framework
Playwright1.57.0UI automation
ESLint8.57.0Code linting
Prettier3.7.4Code formatting

Platform-Specific Code

Electron Desktop

Entry point: src/electron.ts
// Main process
const mainWindow = new BrowserWindow({
  width: 1200,
  height: 800,
  webPreferences: {
    nodeIntegration: true,
    contextIsolation: false,
  },
})

mainWindow.loadFile('app/dist/index.html')
Features:
  • Native menu bar (src/MenuTemplate.ts)
  • Auto-updater (src/autoUpdater.ts)
  • Crash reporting (src/registerCrashReporter.ts)
  • macOS notarization (see NOTARIZATION.md)

Browser Mode

Entry point: src/server.ts
const app = express()
const server = http.createServer(app)
const io = new Server(server)

// Serve static files
app.use(express.static('app/dist'))

// Socket.IO for MQTT communication
io.on('connection', (socket) => {
  // Handle MQTT operations
})

server.listen(3000)
Features:
  • Authentication (src/AuthManager.ts)
  • Rate limiting (express-rate-limit)
  • Security headers (helmet)
  • Session management
  • Docker deployment support
See BROWSER_MODE.md for details.

Extension Points

Adding a Message Decoder

1

Create Decoder

// app/src/decoders/MyDecoder.ts
export class MyDecoder implements Decoder {
  canDecode(topic: string): boolean {
    return topic.includes('myformat')
  }
  
  decode(buffer: Buffer): any {
    // Decode logic
  }
}
2

Register Decoder

Add to decoder registry in app/src/decoders/index.ts
3

Add Tests

Create MyDecoder.spec.ts with test cases

Adding a UI Component

1

Create Component

// app/src/components/MyComponent/MyComponent.tsx
import { withStyles } from '@mui/styles'

const MyComponent = ({ classes }) => {
  return <div className={classes.root}>Content</div>
}

export default withStyles(styles)(MyComponent)
2

Add Styles

3

Connect to Redux

import { connect } from 'react-redux'

const mapStateToProps = (state) => ({ /* ... */ })
export default connect(mapStateToProps)(MyComponent)

Build Process

Webpack Configuration

Desktop mode: app/webpack.config.js
  • Target: electron-renderer
  • Entry: app/src/index.tsx
  • Output: app/dist/bundle.js
Browser mode: app/webpack.browser.config.mjs
  • Target: web
  • Entry: app/src/index.tsx
  • Output: app/dist/bundle.js
  • Dev server on port 3000

TypeScript Compilation

# Root tsconfig.json compiles:
# - src/ (Electron & server)
# - backend/src/ (models)

npx tsc  # Outputs to dist/
App has its own app/tsconfig.json for Webpack integration.

Performance Considerations

Topic Tree Optimization

  • Uses Map for O(1) child lookup
  • Lazy rendering with react-window for large trees
  • Memoized selectors to prevent unnecessary renders

Message History

  • Circular buffer for chart data (configurable limit)
  • Automatic pruning of old messages
  • Efficient diff calculation for updates

Bundle Size

# Analyze bundle
cd app && npx webpack-bundle-analyzer stats.json
Current sizes (production build):
  • Main bundle: ~2.5 MB (includes Material-UI, D3)
  • Vendor bundle: ~1.8 MB
  • Total: ~4.3 MB (before gzip)

Testing Architecture

See Testing Guide for comprehensive test documentation. Test locations:
  • Unit tests: app/src/**/*.spec.tsx, backend/src/spec/
  • UI tests: src/spec/ui-tests.spec.ts
  • LLM tests: app/src/services/spec/

Security Architecture

Security considerations:
  • API keys stored in localStorage (browser) or encrypted storage (Electron)
  • Password authentication uses bcrypt with 10 rounds
  • Rate limiting on authentication endpoints
  • Helmet.js security headers in browser mode
  • No server-side data storage of MQTT credentials
See SECURITY.md for security policy.

Deployment Architecture

Desktop Releases

  • Electron Builder creates platform-specific packages
  • macOS: DMG with notarization
  • Windows: NSIS installer + portable
  • Linux: AppImage, deb, snap

Docker Container

  • Multi-stage build for minimal image size
  • Multi-arch support (amd64, arm64, arm/v7)
  • Environment-based configuration
  • Volume mount for persistent data
See DOCKER.md for deployment guide.

Next Steps

Testing

Learn the testing strategy and write tests

Styling

Follow Material-UI styling conventions