Building an Elite Dangerous Community Platform
Our Elite Dangerous group, Slevinth Heaven, has been flying together for a while now. We run everything from quiet exploration trips to coordinated combat operations in conflict zones, and somewhere along the way the usual pattern emerged: someone would ask how the group was doing, and the honest answer was “I have no idea, I’d have to dig through my journal files.” Elite’s journal system is remarkably detailed, but it’s flat JSON written to disk as you play. Great for toolmakers, not great for casually checking how many kills you racked up last weekend.
I wanted a place where the whole group could see each other’s progress at a glance, without any of us having to manually export anything. So I built SHED: Slevinth Heaven Elite Dangerous. It went from first commit on 22 March 2026 to a live platform at elite.sweetffa.com in under three weeks of active development.
Picking the stack
The core requirement was a web dashboard anyone in the group could visit without installing anything. But Elite runs on Windows, and reading journal files in real time is much easier with a native app running alongside the game. That pointed me toward two separate clients talking to a shared backend.
I chose Blazor Server for the web frontend. I’m most comfortable in .NET, and Blazor’s component model feels natural for a dashboard full of stats cards and live-updating lists. Running server-side keeps the auth logic and data access straightforward, and I didn’t need the complexity of a separate SPA build step. The desktop client is a WPF application using WinUI 3 controls; it monitors the journal directory, processes events in real time, and periodically uploads journal files to the API. Everything shares a common Core library with all the event models, so the journal parsing logic is written once and used everywhere.
The backend is ASP.NET Core, hosted in Docker behind nginx on a VPS. Journal files get stored to disk and processed by a background service. Commander profiles are persisted as JSON files keyed by Frontier ID, which is simple enough for the scale we need and trivially inspectable when something goes wrong.
Authentication deserves a mention because it solves the “only you should upload to your profile” problem quite elegantly. The desktop client authenticates via Frontier’s OAuth 2.0 PKCE flow: it opens a browser to the Frontier auth endpoint, spins up a local HTTP listener on a random port to catch the callback, and exchanges the code for tokens. When the desktop app posts a journal file to the API, it sends the Frontier access token as a Bearer header. The server validates that token against Frontier’s Companion API on the first request, caches the result for five minutes (keyed on a SHA-256 hash of the token, never the raw token itself), and extracts the commander name and Frontier ID. This means the API never needs its own user database; Frontier’s auth system is the source of truth.
The journal pipeline
Elite Dangerous writes a new journal file each session, with one JSON object per line. The desktop app watches the journal directory, reads new lines as they arrive, and fires them through a JournalEventService that dispatches them to whichever services care about them: CombatService, ExoBioService, RankService, CommanderStatsService, and so on. Each service maintains in-memory state and raises strongly-typed events that ViewModels subscribe to. The CombatViewModel, for example, subscribes to KillLogged, StatsChanged, and DataLoaded from CombatService, and separately to RankUpdated and ProgressUpdated from RankService. Everything flows on the WinUI dispatcher queue so the UI stays responsive.
On the server side, the desktop app periodically uploads the raw journal files to the JournalController. The API saves them to disk immediately and returns success; a background JournalProcessingService picks them up every 30 seconds. The processor tracks a manifest per commander that records which files have been processed and how many lines each one had. On subsequent runs it skips already-processed lines, so incremental uploads are fast. If the processing schema version is bumped (because I’ve added support for new event types), the whole manifest is invalidated and everything is reprocessed from scratch. It’s a simple approach, but it means I can add new features without worrying about whether existing data is stale.
Combat log
The combat log was the first feature I built beyond basic rank display. Every time you destroy a ship in Elite, the journal records a Died event for the victim (or a PVPKill event for player targets), along with bounty vouchers and combat bond payments. The CombatService processes these into a running kill log, aggregates totals for NPC kills, PvP kills, bounty credits, combat bond credits, and capital ship bond credits, and tracks murkier stats like your worst hull damage reading since you last docked, crime count, and interdiction success/failure rates.
The interesting bit is the kills-to-next-rank estimator. Combat rank progression in Elite is based on an internal point score that varies depending on the rank of your target relative to your own rank. The CombatRankHelper class encodes the known point thresholds and calculates estimates for five scenarios: fighting opponents two ranks above you, one rank above, equal rank, one rank below, and two ranks below. At Dangerous rank you might need 2,000 kills against equal-rank opponents but only 400 against someone two ranks higher. Being able to see that in the app while you’re planning your next combat session is genuinely useful.
On the web side, the Blazor commander profile page shows a paginated kill log with ship type, faction, and system for each entry, plus summary cards for total kills, total earnings broken down by bounty type, and the top five factions you’ve been fighting against.
Bank balance and economic tracking
Wealth in Elite has two distinct numbers. “Net worth” is what the Statistics event reports: the total value of everything you own, including ships and modules. “Bank balance” (or wallet balance) is the liquid credits you actually have on hand, which appears in the LoadGame event at each session start. Both matter, and people in the group kept asking each other “what’s your balance now?” after expensive ship purchases, so tracking both was an obvious feature.
The CommanderStatsViewModel exposes both CurrentWealthFormatted and WalletBalanceFormatted, sourcing them from the respective journal events. The API’s commander profile includes both figures, but the wallet balance is marked as owner-only: other commanders can see your net worth, but not exactly how much liquid cash you’re sitting on. Small privacy touch, but it felt right.
Beyond raw balance, the stats model tracks lifetime earnings broken down by category: exploration profits, market profits, mining profits, exobiology profits, and bounty hunting profit. This gives a genuinely interesting picture of how each commander generates credits. One person is primarily a trader with hundreds of markets traded; another has made most of their money from exobiology; a third lives off bounties. You can see that at a glance on the profile page.
Exobiology: tracking what you’ve found and what you haven’t sold yet
Exobiology is Elite’s most profitable activity for patient explorers, but it involves a lot of mental bookkeeping. You scan organisms across multiple planets over potentially many sessions, and you can’t sell a species until you’ve collected three samples from it. The payout when you finally reach a Vista Genomics station can be enormous, but only if you remember what you’ve still got pending.
The ExoBioService tracks the full scan lifecycle from ScanOrganic events. Each organism goes through three stages: Log (first sample), Sample (second sample), and Analyse (third sample, scan complete). The ExoBioViewModel shows cards for in-progress scans with the estimated value and any first-footfall bonus, clears incomplete scans when you move to a new body (matching the game’s own behaviour), and updates the total when you submit samples at a station.
The sales history view in the web app includes a feature I’m quite pleased with: cluster highlighting. When you sell exobiology data, the handler checks all your past sales and flags individual species that appear in multiple systems within 100 light-years of each other and are worth at least 7 million credits each. Those entries get visually highlighted to indicate a potential hotspot. It’s a rough heuristic, but it gives explorers a starting point for “where should I go next to farm this species?”
Purchases, sales, and market data
Market activity, ship purchases, and module sales feed into the economy summary. The journal covers these through MarketBuy, MarketSell, ShipyardBuy, ShipyardSell, and related events. On the server, market profit figures and trade statistics are extracted during journal processing and stored in the commander stats model. The CommanderStatsService on the desktop side surfaces the same data live while you’re playing, so you can watch your trade profit number tick up across a session.
The API also publishes commodity price data to the EDDN (Elite Dangerous Data Network) network via the EddnPublisherService. EDDN is the community database that third-party tools like EDDB and Spansh rely on for up-to-date market prices. When the desktop app uploads fresh journal data, the processing service forwards commodity events to EDDN so our activity contributes back to the wider community tooling ecosystem. The EDDN publisher only runs during incremental processing, not during a full reprocess of historical data, so we’re not flooding the network with stale prices.
Where things stand now
The platform is live and all of us in the group are using it. Every feature described above is deployed. The Blazor web app shows the commander list on the home page, links through to individual profiles with ranks, reputation, stats, combat log, exobiology sales history, codex entries, and visited systems. The WPF desktop app has a full tabbed interface covering general stats, combat, exobiology (active tracking and sales history), exploration, codex, and FSD timing tools. There’s also a heads-up overlay window that logs combat events without covering the game’s interface.
The planned roadmap includes a mining log, trade route history, fleet carrier tracking, an exploration heat map, mission history, and Discord notifications for rank milestones and high-value events. The Discord integration is probably next on my list because it’s the most social feature: getting a message in the group chat when someone hits a new combat rank or sells a particularly enormous exobiology haul would suit the group’s dynamic well.
The full project is on GitHub at LuckyNoS7evin/slevinth-heaven-elite-dangerous if you want to take a look at the code, and the live site is at elite.sweetffa.com. If you run your own Elite Dangerous group and want to self-host it, everything deploys with a single docker compose up.