An external dashboard and data bridge for Starsector. NexusUI opens interactive panels outside the game window — perfect for multi-monitor setups where you want fleet stats, colony income, faction relations, or cheat tools on a second screen while playing.
It also exposes a localhost REST API, letting external tools (browsers, scripts, companion apps) read live game data and execute commands.
Starsector runs fullscreen on your primary monitor. If you have a second screen, it sits there doing nothing. NexusUI changes that:
- Drag dashboard windows to your second monitor — fleet overview, cargo, colonies, faction relations — all live-updating while you play
- Open multiple windows — fleet stats on one screen, cheats panel on another, profiler in a corner
- Build companion web apps — the REST API serves live game data as JSON on
localhost:5959 - Execute game commands from outside — thread-safe command queue lets external tools add credits, spawn ships, or modify game state
The panels are independent OS windows (Swing), not in-game UI. They float freely across all your monitors, resize, and stay open while you play.
- External Dashboard Windows — Themed Swing windows with tabbed pages, draggable and resizable, that live outside the game window on any monitor
- Multi-Window Support — Each click opens a new independent window with its own page state; arrange them across monitors however you like
- REST API Bridge — Embedded HTTP server (
127.0.0.1:5959) exposing fleet, cargo, colonies, and factions as JSON endpoints with CORS - Thread-safe Command Queue — Safely execute game-state modifications from Swing panels or HTTP requests via
GameDataBridge - Floating Campaign Button — Draggable "N" button on the campaign map to quickly open a dashboard window
- Page Registration API —
NexusPage/NexusPageFactoryinterfaces for mods to add their own dashboard panels - Themed Drawing Utilities — Color palette, fonts, and helpers (
drawCardBg,drawCardHeader,drawLabeledBar,drawRelationBar) for consistent panel styling - Tripad Extension Integration — When Tripad Extension is installed, the campaign button is managed by Tripad's unified button bar
- Install LazyLib if you haven't already
- Download the latest release
- Extract to your
Starsector/mods/directory - Enable NexusUI in the Starsector launcher
- Load a save in Starsector
- Click the floating N button on the campaign map (or use a Tripad Extension button)
- A dashboard window appears — drag it to your second monitor
- Click the N button again to open more windows
- Each window updates live every ~3 seconds while you play
com.nexusui
├── api/
│ ├── NexusPage # Interface: dashboard panels
│ └── NexusPageFactory # Interface: per-window page instances
├── bridge/
│ └── GameDataBridge # Game thread data cache + command queue
├── core/
│ └── NexusModPlugin # Mod entry point, server lifecycle
├── overlay/
│ ├── NexusFrame # External Swing window with tabs + drawing utils
│ └── NexusOverlay # Campaign map floating button (OpenGL)
└── server/
└── NexusHttpServer # Embedded localhost HTTP server
1. Add NexusUI as a dependency in your mod_info.json:
{
"dependencies": [
{"id": "nexus_ui", "name": "NexusUI"}
]
}2. Implement NexusPage:
import com.nexusui.api.NexusPage;
import javax.swing.JPanel;
public class MyPage implements NexusPage {
public String getId() { return "my_mod_page"; }
public String getTitle() { return "My Mod"; }
public JPanel createPanel(int port) {
JPanel panel = new JPanel();
// Build your Swing UI here
// 'port' is the HTTP server port (5959) for REST calls
return panel;
}
public void refresh() {
// Called every ~3 seconds to update data
}
}3. Register in your ModPlugin:
import com.nexusui.overlay.NexusFrame;
@Override
public void onGameLoad(boolean newGame) {
NexusFrame.registerPage(new MyPage());
}Each toggle() call creates a new independent window. Use NexusPageFactory so each window gets its own page state — essential for multi-monitor setups where users may open several windows:
import com.nexusui.api.NexusPageFactory;
import com.nexusui.api.NexusPage;
import com.nexusui.overlay.NexusFrame;
NexusFrame.registerPageFactory(new NexusPageFactory() {
public String getId() { return "my_page"; }
public String getTitle() { return "My Mod"; }
public NexusPage create() { return new MyPage(); }
});If your mod should work with or without NexusUI installed, do NOT add it to dependencies. Use lazy class loading instead:
Starsector's security sandbox blocks reflection (
Class.forName,getMethod,invokeall throwSecurityException). Use theisModEnabled()guard below — Java loads classes lazily, soMyNexusIntegrationwon't resolve unless theifblock executes.
1. Create a helper class that imports NexusUI types:
import com.nexusui.api.NexusPage;
import com.nexusui.api.NexusPageFactory;
import com.nexusui.overlay.NexusFrame;
public class MyNexusIntegration {
public static void register() {
NexusFrame.registerPageFactory(new NexusPageFactory() {
public String getId() { return "my_page"; }
public String getTitle() { return "My Mod"; }
public NexusPage create() { return new MyPage(); }
});
}
}2. Guard the call in your ModPlugin:
if (Global.getSettings().getModManager().isModEnabled("nexus_ui")) {
try {
MyNexusIntegration.register();
} catch (Throwable e) {
log.warn("NexusUI integration failed: " + e.getMessage());
}
}Execute game-state changes safely from Swing panels or HTTP handlers:
import com.nexusui.bridge.GameDataBridge;
String cmdId = GameDataBridge.getInstance().enqueueCommand(new GameDataBridge.GameCommand() {
public String execute() {
// Runs on the game thread — safe to use all game APIs
Global.getSector().getPlayerFleet().getCargo().getCredits().add(1000);
return "{\"success\":true}";
}
});
// Poll for result (non-blocking, returns null if not ready)
String result = GameDataBridge.getInstance().pollCommandResult(cmdId);Expose mod-specific data via the REST API for external tools:
GameDataBridge.getInstance().registerProvider("mymod", new GameDataBridge.DataProvider() {
public String getData() {
return "{\"status\":\"active\",\"count\":42}";
}
});
// Accessible at: GET http://127.0.0.1:5959/api/v1/custom/mymodNexusFrame provides static helpers for building themed Swing panels:
| Method | Description |
|---|---|
drawCardBg(g2, x, y, w, h) |
Rounded card background with border (8px radius) |
drawCardHeader(g2, x, y, w, title, badge) |
Gradient header with title and optional badge |
drawLabeledBar(g2, x, y, w, h, label, value, pct, color) |
Progress bar (0.0–1.0 scale) |
drawRelationBar(g2, x, y, w, h, name, relation, color) |
Centered relation bar (-100 to +100) |
formatNumber(long) |
Format with K/M suffixes: 1234 → "1.2K" |
prettifyId(String) |
"heavy_machinery" → "Heavy machinery" |
truncate(String, int) |
Truncate with ellipsis |
| Constant | RGB | Usage |
|---|---|---|
BG_PRIMARY |
(10, 14, 23) |
Main background |
BG_SECONDARY |
(17, 24, 39) |
Title bar, secondary panels |
BG_CARD |
(21, 29, 46) |
Card backgrounds |
CYAN |
(100, 220, 255) |
Primary accent |
GREEN |
(100, 255, 100) |
Positive values |
ORANGE |
(255, 180, 50) |
Warnings |
RED |
(255, 80, 80) |
Negative values |
TEXT_PRIMARY |
(220, 225, 232) |
Main text |
TEXT_SECONDARY |
(138, 149, 168) |
Secondary text |
| Constant | Font | Usage |
|---|---|---|
FONT_TITLE |
Consolas Bold 14 | Page titles |
FONT_HEADER |
Consolas Bold 12 | Section headers |
FONT_BODY |
Segoe UI 12 | Body text |
FONT_MONO |
Consolas 11 | Monospace data |
FONT_SMALL |
Consolas 10 | Small labels |
All endpoints return JSON. CORS is enabled. Server binds to 127.0.0.1:5959 (localhost only).
| Endpoint | Description |
|---|---|
GET /api/v1/game |
Player name, faction, credits, date, total ships |
GET /api/v1/fleet |
Fleet composition, ship details, CR, strength |
GET /api/v1/cargo |
Credits, cargo space, fuel, supplies, crew, commodities |
GET /api/v1/colonies |
Player colonies, industries, income, stability |
GET /api/v1/factions |
All factions with relation values and rep levels |
GET /api/v1/custom/{key} |
Custom data from registered DataProviders |
Data is cached on the game thread and updated every 5 seconds (only when the overlay is visible).
fetch('http://127.0.0.1:5959/api/v1/fleet')
.then(r => r.json())
.then(fleet => {
console.log(fleet.totalShips + ' ships, ' + fleet.capitals + ' capitals');
fleet.members.forEach(ship => {
console.log(ship.shipName + ' — CR: ' + ship.cr + '%');
});
});Since the API serves JSON with CORS enabled, you can build a standalone web page that reads live game data:
<script>
setInterval(async () => {
const game = await (await fetch('http://127.0.0.1:5959/api/v1/game')).json();
document.getElementById('credits').textContent = game.credits.toLocaleString();
document.getElementById('date').textContent = game.dateString;
}, 5000);
</script>| Constant | Value | Location |
|---|---|---|
NexusModPlugin.MOD_ID |
"nexus_ui" |
Mod identifier |
NexusModPlugin.DEFAULT_PORT |
5959 |
HTTP server port |
NexusModPlugin.VERSION |
"0.9.0-beta" |
Current version |
- NexusDashboard — Fleet composition, combat readiness, faction relations, cargo, and colonies overview
- NexusCheats — Add credits, resources, weapons, ships, XP, and story points
- NexusProfiler — Real-time FPS, memory, GC pause tracking, and performance diagnostics
- NexusColony — Remote colony management — build, upgrade, and manage industries across all player colonies
- NexusTactical — Real-time combat fleet status visualization
- TripadExtension — Modular floating button framework for the campaign map
I won't be posting this on the Fractal Softworks forums myself for personal reasons, but if you'd like to share it there, you're absolutely free to do so.
If you have suggestions, bug reports, or feature requests, feel free to open an issue.