The Complete Journey
The full engineering blog series in one page. From dark mode to cross-platform.
Rebuilding EVEMon for the Next Decade
A multi-part series documenting the complete journey from a broken tool to a cross-platform application running on Windows, Mac, and Linux. Written for EVE players, engineers, and anyone curious about what happens when you pull one thread and the whole building unravels.
Series Overview
| Part | Title | Audience | Length |
|---|---|---|---|
| 1 | One Thread Pulled Another | Everyone | 10 min |
| 2 | The God Object Has 69 Static Events | Engineers | 15 min |
| 3 | Surgery on a Beating Heart | Engineers + Curious Players | 12 min |
| 4 | The Scheduler Was Broken All Along | Engineers | 15 min |
| 5 | 101,000 Lines and Zero ViewModels | Engineers | 12 min |
| 6 | I Replaced the Entire UI Framework | Everyone | 10 min |
| 7 | Ship It | Everyone | 15 min |
Part 1: One Thread Pulled Another
For everyone. No engineering background needed.
I didn't set out to rebuild EVEMon. I set out to help.
I'm an EVE Online player. I multibox dozens of characters. Like every serious player, I use EVEMon — the skill planning tool that's been part of EVE life since 2006. Twenty years. Fifty-seven contributors. Nearly ten thousand commits. A tool so essential that EVE University lists it in two separate categories on their tools page — the only tool that holds that distinction.
And like every player who stares at EVEMon at 3am, I wanted dark mode.
EVEMon hadn't had a meaningful update in nearly five years. The last commit was March 17, 2021. Nineteen hundred days of silence. There was a community fork that kept it running, but it was the same white Windows-only application from 2006. Nobody was adding dark mode. Nobody was making it work on Linux or Mac. The project that fifty-seven people had built over two decades was slowly going stale.
I thought: I'll just help. I'll fork it, fix some bugs, maybe add dark mode. I'm not a developer by training — I don't have a CS degree — but I'd been using Claude Code for other projects and I knew I could direct it to do meaningful work on a codebase.
What I didn't know was that "just help" would turn into seven weeks, roughly $5,000 in API costs, and a complete application rebuild. Because every thread I pulled unraveled another thread behind it.
02What I Found
Imagine a house built over 20 years by 57 different people. Some added rooms. Some knocked down walls. Some put the plumbing through the bedroom because that's where they needed it. Nobody drew blueprints. The house works — you can live in it — but if you try to change the color of one wall, you discover the wall is load-bearing, the paint is mixed into the concrete, and the electrical wiring runs through the paint.
That's what EVEMon's code looked like.
Here are the numbers. I'm not going to explain every technical term — what matters is the scale.
The original codebase:
The last point deserves emphasis. The codebase contained a complete web server for EVE's In-Game Browser — which CCP removed from the game in 2017. It had a driver for the Logitech G15 keyboard's LCD screen — hardware discontinued in 2008. It had a Certificate Browser for a game system CCP removed in 2014. It had integration with Hammertime, BattleClinic, EVE-Central, and Osmium — all websites that have shut down. Eighteen thousand lines of code talking to things that don't exist anymore.
03Why I Couldn't Just Add Dark Mode
Here's the thing about dark mode in a modern application: you change one setting and every screen goes dark. That's because modern apps separate how things look from how things work. The look is defined in one place. Change it once, it changes everywhere.
EVEMon didn't work that way. It was built in 2006 using Windows Forms — Microsoft's screen-drawing system from 2002. In WinForms, every button, every list, every label has its color set by hand, one at a time, in the code that draws it. Want dark mode? You need to find and change the color on every single control, across every single screen.
But the real problem was deeper. The code that decided what to show and the code that decided how to show it were tangled together. The business logic — skill calculations, market orders, character data — was mixed in with the screen-drawing code at the source level. Sixty-six files in the "business logic" part of the app imported Windows-specific screen-drawing libraries. You literally could not separate the data processing from the Windows UI without untangling 66 files first.
Dark mode wasn't a cosmetic task. It was an architecture task.
04The Decision
I had two choices:
Option A: Hack dark mode onto the existing system. Change colors one control at a time. Weeks of painful, platform-specific work. At the end: a Windows-only application from 2006 with a dark coat of paint.
Option B: Fix the architecture first. Separate what the app does from how it looks. Then replace the entire screen-drawing system with something modern that has dark mode built in — and gets Linux and Mac support for free.
I chose Option B.
05What Actually Happened
Every thread I pulled revealed another thread:
- Dark mode required separating the screen from the logic.
- Separating the screen required splitting the monolith (one massive project) into smaller pieces.
- Splitting the monolith required replacing the 69 static events with a proper messaging system.
- Replacing the events revealed the scheduling system was broken — it was trying to do 930 things per second on the same thread that draws the screen.
- Fixing the scheduler required a ground-up rewrite with proper rate limiting.
- The rewrite enabled features nobody had imagined.
- The features required a new screen-drawing framework.
- The new framework gave us Windows, Linux, and Mac support.
One thread. Seven weeks. An entire application transformed.
06By the Numbers
Here's what changed in 57 days:
| What | Before (March 2021) | After (March 2026) |
|---|---|---|
| Automated tests (safety checks) | 23 | 1,554 |
| Screen-drawing framework | Windows-only (2002) | Cross-platform (2024) |
| Operating systems | Windows | Windows + Linux + Mac |
| Color themes | 0 | 6 (EVE faction-inspired) |
| Safety rules enforced by code | 0 | 14 |
| Lines of dead code removed | — | 18,072 |
| Skill visualization | None | GPU-accelerated star map |
| ESI scope control | All or nothing | Per-permission granular |
| Privacy mode | None | 6-category masking |
Every number in this table was verified by reading both codebases file by file. Nothing is estimated.
In the next part, I'll explain the 69 static events — what they were, why they were a problem, and how replacing them with 243 lines of code changed everything.
Part 2: The God Object Has 69 Static Events
For engineers. Technical depth ahead.
Before I could separate the UI from the logic, I needed to understand how they communicated. The answer was EveMonClient — and it was worse than I expected.
The God Object
Every application needs some way for its parts to talk to each other. When your skills update from CCP's API, the screen needs to know. When you change a setting, multiple parts of the app need to react. When the timer ticks, dozens of things need to happen.
EVEMon solved this with one class that did everything: EveMonClient. A public static partial class split across two files. 1,856 lines. 69 static events. 929 references from 150 files.
// The old way — repeated 218 times across the codebase
EveMonClient.CharacterUpdated += OnCharacterUpdated;
EveMonClient.SettingsChanged += OnSettingsChanged;
EveMonClient.TimerTick += OnTimerTick;
// ... up to 69 distinct event typesThis is the software equivalent of an office building where every announcement goes over a single PA system. When someone joins a room, they turn on their speaker. When they leave, they're supposed to turn it off. But nobody remembers.
The forensic analysis found:
+=) across the codebase-=)The top subscriber was TimerTick with 35 listeners. It fired every single second on the UI thread. Thirty-five delegate invocations per second, synchronously, on the thread responsible for drawing the screen. With 30 characters loaded, that meant 930 additional QueryMonitor poll checks per second on top of those 35.
The Four Problems
Memory leaks. The += operator creates a reference from EveMonClient to the subscribing screen. If the screen closes but doesn't -= unsubscribe (which happened in at least 6 places), the screen stays in memory forever, still receiving events. Open and close the skill planner ten times, and you have ten phantom skill planners consuming memory and CPU.
Untestable. The events were static — attached to the class itself, not an instance. You couldn't swap them for testing. To test any code that used events, you needed the real EveMonClient initialized, which needed Settings initialized, which needed file system access. Nothing could be tested in isolation. This is why the original codebase had only 23 tests for 210,002 lines of code.
Threading bugs. Events fired from background threads needed to reach the UI thread. The original used ThreadSafeInvoke with blocking BeginInvoke/EndInvoke calls. This was slow and could deadlock if the UI thread was waiting for the background thread while the background thread was waiting for the UI thread.
Cascade overload. When 100 characters updated simultaneously, 100 CharacterUpdated events fired in rapid succession, each triggering a screen refresh. The UI stuttered. Sometimes it crashed.
The EventAggregator: 243 Lines
The replacement is a central message bus where components publish and subscribe to typed events. Every subscription returns a disposable token — drop the token, and the subscription is automatically cleaned up. No more leaked speakers.
// The new way — auto-tracked, auto-disposed
_sub = AppServices.EventAggregator.Subscribe<CharacterUpdatedEvent>(OnUpdate);
// When the screen closes: _sub.Dispose() — guaranteed cleanupImplementation: 243 lines. Thread-safe via ConcurrentDictionary. Supports both strong and weak references. Catches handler exceptions so one failing subscriber never breaks others. Cleans dead weak references lazily during Publish().
Instead of 69 generic EventHandler delegates, every event became its own class: CharacterUpdatedEvent, SettingsChangedEvent, MarketOrdersUpdatedEvent. The compiler catches type mistakes. Per-character filtering was added — each character only receives its own events instead of every character checking "is this about me?" on every fire.
The migration was a Strangler Fig: I wrapped the old system with the new one. Old events fired through the EventAggregator. New code subscribed directly. Over time, the old events were removed one by one.
The key commits on February 15th:
bee27ed3 — Complete UI event migration to EventAggregator
bdbc08d3 — Remove 67 dead static events from EveMonClient.Events.cs (-410 lines)
a935f971 — Complete event migration, async safety, remove dual channels67 dead OnXxx() bridge methods deleted. 410 lines of dead code removed. The god object went from 1,856 lines to about 650 lines of passive initialization.
Verified by 23 tests (EventAggregator E2E + scale): 500 concurrent publishers, 100 subscribers, 1000 concurrent threads, re-entrant publish at 10 levels deep. All passing.
Next: How I split 846 files into 6 assemblies without breaking anything.
Part 3: Surgery on a Beating Heart
For engineers and curious players.
With the EventAggregator handling communication, I could see the real structure of the codebase. And the structure was: there is no structure.
10The House With No Walls
EVEMon.Common. 846 files. 83,656 lines. One single project. Everything lived in one room.
In practical terms: changing how market orders display could break skill plan calculations. You couldn't work on the networking code without dragging in the entire Windows screen-drawing framework. There was no way to enforce rules about what code was allowed to talk to what.
I traced the contamination. 66 files in the "business logic" project imported Windows Forms. They broke into five categories:
| Root Cause | Files | How Deep |
|---|---|---|
| UI thread marshaling via Control.Invoke | 5 | Shallow |
| MessageBox.Show() in business logic | 8 | Shallow |
| 29 visual controls living in the wrong project | 29 | Replace entirely |
| System.Drawing.Image in model properties | 5 | Medium |
| Window management via static factories | 3 | Shallow |
55 files contaminated. But only 14 needed actual code changes. The coupling was wide but shallow.
11The Split
I designed 6 assemblies forming an acyclic dependency graph — dependencies only flow downward:
EveLens.Core (38 files) — Interfaces only. Zero dependencies. The "constitution."
EveLens.Data (173 files) — Enums, constants, static game data.
EveLens.Serialization (188 files) — API response formats, settings formats.
EveLens.Models (32 files) — Characters, Skills, Plans.
EveLens.Infrastructure (31 files) — EventAggregator, logging, scheduling.
EveLens.Common (507 files) — Services, settings, ViewModels. The reduced core.464 files extracted from Common. Each layer has a clear responsibility. A test file (AssemblyBoundaryTests.cs, 325 lines) uses DFS cycle detection to verify no assembly references one above it. If someone accidentally creates a circular dependency, the build fails with a message like "EveLens.Core -> EveLens.Common -> EveLens.Core".
For non-engineers: Think of it like this. The old codebase was a single huge warehouse where everything was stored together — food next to chemicals next to electronics. The new codebase is a proper building with labeled rooms, fire doors between sections, and rules about what goes where. If someone tries to put food in the chemical storage, an alarm goes off.
1214 Architectural Laws
During the split, patterns emerged — things that kept going wrong in predictable ways. I codified them into rules and made the rules enforceable by automated tests:
- No static mutable state — everything through interfaces
- No god objects — no class over 500 lines
- Dependencies flow downward only — enforced by tests
- New services must be testable
- Events through EventAggregator only — no static events
- Lazy by default — expensive objects created on first use
- No sync-over-async — no blocking on async code
- Right file, right assembly
- EveMonClient is frozen — never add to it
- All async void must have try/catch
- Event subscriptions must be disposed
- Tests prove behavior — no feature without a test
- Serialization DTOs are the data contract
- No direct EveMonClient access from UI
Each law has a corresponding automated test. The architecture can't regress because the tests won't let it. 32 architecture enforcement tests run on every build.
Next: What the diagnostic stream revealed in its first 60 seconds.
Part 4: The Scheduler Was Broken All Along
For engineers. Deep technical content.
Before I could build a new UI, I needed to know what the application was actually doing underneath the old one. The only diagnostic tool was a trace log file — unstructured text you had to find on disk and open in Notepad. No real-time visibility. No structured data.
13Building the Diagnostic Stream
I built a TCP server on port 5555 that broadcasts structured JSON events in real-time:
nc localhost 5555 | jq '.msg'
# Output: GET /characters/12345/skills -> 304 Not Modified (89ms)221 lines of code. Every ESI HTTP request with URL, status code, and timing. Every EventAggregator dispatch. Every scheduler decision.
I turned it on, added my characters, and watched.
14What I Saw
The entire ESI scheduling system was fundamentally broken.
How it worked: A timer fired every second on the UI thread. Each tick, 930 QueryMonitor instances (31 per character × 30 characters) independently checked their own timers and decided whether to fire an API call.
The problems:
- Thundering herd: On startup, all 930 monitors fired simultaneously. 240+ HTTP requests hit CCP's API at once.
- New HttpClient per request:
new HttpClient(new HttpClientHandler())for every single API call — the classic socket exhaustion anti-pattern. - UI thread blocking: Every API response blocked a thread pool thread on
Dispatcher.Invoke()waiting for the UI thread. But the UI thread was busy processing the next tick's 930 checks. - No proactive rate limiting: The only control was a reactive error threshold — stop everything when you're about to get throttled. No per-character awareness.
- Round-robin starvation: With 100 characters, character #100 waited over 8 minutes for its first data fetch.
- ETag discarded on pages 2+: Paged queries explicitly nulled out the ETag on subsequent pages, defeating conditional GET optimization.
async voidwithout try/catch: 3 timer handlers could crash the entire app on any unhandled exception.
The New EsiScheduler
I replaced everything with a priority-queue scheduler on a dedicated background thread. 973 lines across 7 focused files:
- Priority queue sorted by cache expiry: Zero wasted polling. Scheduler sleeps until the next job is due.
- Background thread: HTTP calls run on the thread pool. UI thread is never blocked.
- Tab-switch awareness: Click a character tab, their data loads instantly.
- 20 concurrent HTTP slots via SemaphoreSlim.
- Per-character rate limiting: 150 tokens per 15 minutes with 10% safety margin.
- Auth failure isolation: A 401 on one character suspends only that character. Others continue.
- Cold-start phasing: Visible character first (0ms), then staggered by index (20ms apart), then low-priority (1 second apart).
- Lazy invalidation: Version stamps allow O(1) job cancellation without scanning the queue.
- 5-consecutive-304 ETag reset: Prevents stale cache nodes from masking data changes.
The diagnostic stream that cost 221 lines to build saved weeks of debugging. And the scheduler bug it uncovered — the thundering herd with 930 UI-thread polls per second — had been silently degrading EVEMon's performance for years.
Next: How 10,000 lines of duplicated code became 1,424.
Part 5: 101,000 Lines and Zero ViewModels
For engineers.
EVEMon had 11 list views showing different character data: Assets, Market Orders, Contracts, Industry Jobs, Wallet Journal, Wallet Transactions, Mail, Notifications, Kill Log, Planetary, and Research Points.
In the original code, each was a self-contained WinForms control containing its own filtering, sorting, and grouping logic. Each was 400 to 1,500 lines. The logic was nearly identical across all 11, but subtly different in each.
421 occurrences of the pattern UpdateContent|IsTextMatching|UpdateSort|UpdateContentByGroup across 47 files. Massive code duplication. Fix a sorting bug in the assets list? The same bug still exists in the other 10.
The Generic Pipeline
ListViewModel<TItem, TColumn, TGrouping> — 384 lines. Concrete implementations provide four things:
GetSourceItems() — where does the data come from?
MatchesFilter() — does this item match the search text?
CompareItems() — how do I compare two items for sorting?
GetGroupKey() — what group does this item belong to?That's it. Everything else — the pipeline execution, the property change notifications, the grouping logic, the sort toggle, the event subscriptions — is handled by the base class.
13 concrete list ViewModels, each 72-160 lines, replacing 400-1,500 lines of inline control code. Total ViewModel layer: 86 files, 13,666 lines (46 production + 10 display wrappers + 30 test files).
For non-engineers: Imagine 11 different factories all building the same product with slight variations. Each factory has its own production line, its own quality checks, its own shipping department. If you find a defect in the quality check, you have to fix it in all 11 factories separately. The ViewModel layer is like building one production line that all 11 factories share. Fix the quality check once, it's fixed everywhere.
Next: I replaced the entire UI framework.
Part 6: I Replaced the Entire UI Framework
For everyone.
This is the part where everyone says I went too far.
The entire old UI was Windows Forms — 99,073 lines of Windows-only code. 251 files. 116 auto-generated designer files. 52 windows and dialogs. 54 custom controls. Zero dark mode. Zero Linux. Zero Mac.
Avalonia is a modern cross-platform framework. Write it once, it runs on Windows, Linux, and Mac. And dark mode? One setting:
RequestedThemeVariant="Dark"One setting versus weeks of manual color changes on hundreds of controls.
17What Got Built
25,639 lines of Avalonia code, written from zero:
- 21 character monitoring views — every data tab ported. Skills with 5-block level indicators. Skill Queue with progress bars. Assets with hierarchical tree browsing. Market Orders. Contracts. Industry Jobs. Wallet. Mail. Notifications. Kill Log. Standings. Contacts. Medals. Loyalty Points. Employment History with a horizontal timeline.
- The Plan Editor — 5 browser tabs (Plan, Skills, Ships, Items, Blueprints). Import fittings from clipboard. Export to file. Keyboard reordering.
- The Skill Constellation — 834 lines of GPU-accelerated code that renders your entire skill tree as a space-themed star map. 400 twinkling background stars. Nebula clouds behind each skill group. Hover a skill and its entire prerequisite chain lights up. Nothing like this exists in any EVE tool.
- 6 EVE-faction dark themes: Dark Space (navy/gold), Caldari Blue (steel/cyan), Amarr Gold (brown/amber), Gallente Green (emerald/silver), Minmatar Rust (copper/orange), Midnight (OLED black/gold).
- ESI Scope Editor — you choose exactly which ESI permissions to authorize. Three presets: Full, Standard, Skill Planner Only. Or customize down to individual scopes.
- Per-category privacy mode — hide your character name, corp, ISK balance, skill points, training queue, or remaps independently. Toggle with an eye icon in the status bar.
- Native notifications — Windows toast notifications, Linux desktop notifications, macOS notification center. All from the same code.
What It Means for Players
For the first time in 20 years, an EVEMon-family tool runs natively on Linux and macOS. No Wine. No emulation. The same application, the same features, on every platform.
The alpha releases tell the Linux story. Alpha.4 through alpha.25 — twenty-two consecutive releases — were spent hunting settings persistence bugs on Linux and macOS. The async dispatcher that works perfectly on Windows deadlocks on X11. The System.Drawing library that renders images on Windows throws exceptions on Linux. The file system APIs that save atomically on NTFS behave differently on ext4. Each of those 22 releases fixed one more edge case, one more platform quirk, one more assumption that Windows made easy and Linux made explicit.
That's what cross-platform really means. Not "it compiles." It works.
Next: What seven weeks of building taught me.
Part 7: Ship It
For everyone.
The Full Arc
Here's the journey nobody sees in the commit log.
I opened a codebase expecting to change a background color. I found a 20-year-old monolith with 69 static events, a broken scheduler doing 930 polls per second on the UI thread, 18,072 lines of dead code talking to services that no longer exist, zero ViewModels, zero tests worth mentioning, and zero possibility of running on anything other than Windows.
Seven weeks later:
| What | Before | After |
|---|---|---|
| Automated safety checks | 23 | 1,554 |
| Operating systems | Windows | Windows + Linux + Mac |
| Color themes | 0 | 6 |
| Static events (god object coupling) | 69 | 0 |
| ViewModels (logic separated from screen) | 0 | 46 |
| Architectural rules enforced by code | 0 | 14 |
| Dead code (talking to dead services) | 18,072 lines | Removed |
| Features working in Avalonia | 0 | 32 |
| Skill visualization | None | GPU-accelerated star map |
| ESI scope control | All or nothing | Per-permission granular |
| Privacy mode | None | 6-category masking |
356 commits. 9,807 total commits across the project's 20-year history. Contributions from 57+ people preserved in the About window — every name, from Six Anari who created it in 2006 to Peter Han who saved it during the ESI migration.
20What I Am
I am not a software engineer. I don't have a computer science degree. I cannot write C# from scratch.
I built EveLens using Claude Code — Anthropic's AI coding tool. I used multiple AI agents in parallel, each with different specialties: architecture analysis, implementation, validation, testing. I cross-validated their findings. I made the architectural decisions. I directed the implementation order.
The AI turned my vision into working software at a speed that shouldn't be possible. But AI couldn't decide what to build. It couldn't decide when the architecture was clean enough. It couldn't decide to credit every contributor in the About window.
This wouldn't be possible without AI. The idea that a single developer can do this on an open source project alone — restructure a 20-year-old codebase, build a new UI framework, ship cross-platform, write 1,511 tests — it's not possible. I spent $5,000 in API costs to make it happen. AI didn't replace the need for a developer. It replaced the need for a team.
21What I Got Wrong
I should have shipped sooner. The community asked for dark mode on January 5th. I could have shipped a rough dark theme in a week. Instead, I spent seven weeks building a perfect foundation. Every individual decision was technically justified. The aggregate effect was nothing shipped for two months.
Features that didn't make it. Booster simulation was attempted in the WinForms era — it didn't work as intended and was not ported. Mass re-auth was worked on but never shipped. Character comparison exists as a placeholder. Three tabs (Planetary, Research Points, Factional Warfare) have code behind them but aren't wired into the UI yet. I'm being honest about this because the moment someone finds an overclaim, the whole thing loses trust.
22What I Got Right
Architecture first. The 14 laws and the assembly boundaries are what made everything else possible. Without clean separation, I'd still be fighting circular dependencies. The ViewModel layer built for the old UI carried over to Avalonia unchanged — zero modifications.
Crediting everyone. The About window names every contributor from the project's 20-year history. Twenty developers. Five consultants. Five community contributors. The original creator. The EVE faction themes. The GPL license text. "EveLens is a complete rebuild of EVEMon — the character monitoring and skill planning tool that's served the EVE Online community since 2006."
Transparency about AI. Every commit noted. Claude Code mentioned in the About window. Stated openly here. Being upfront about it lets me focus on what matters — does the product work?
23What This Means for EVE
EVEMon was created in August 2006, the same year EVE's subscriber base was exploding. For nineteen years, through three generations of maintainers, it served as the tool every serious player opened alongside the game client.
When CCP retired the XML API in 2018, Peter Han saved it with the ESI migration. When Peter Han's fork went dormant, the accumulated wisdom of 57 contributors and nearly 5,000 commits risked being lost.
EveLens preserves that wisdom while rebuilding the foundation. The skill calculations still work exactly as they did when Jimi C refined them in 2011. The plan optimizer still finds the same optimal paths. The ESI integration still handles the same edge cases Peter Han debugged in 2018.
But now it runs on Linux. And Mac. And has dark mode. And 1,554 tests making sure none of it breaks.
24What Comes Next
EveLens is alpha. Things will break. I'll fix them.
Immediate priorities:
- Wire the remaining 3 tabs (Planetary, Research Points, Factional Warfare)
- Build Character Comparison
- Continue strangling the 122 remaining god object references
- Whatever people want, will be built in
The code is open source. The git history is public. The architectural laws are enforced by tests. Anyone can contribute.
25The Lineage
EveLens was built on the EVEMon foundation created by Six Anari in 2006 and maintained through the years by Jimi Charalampidis (5,886 commits), Richard Slater (1,494 commits), BradStone (526 commits), Peter Han (328 commits), and 53 other contributors. Their work is the bedrock that EveLens stands on. The About window names every one of them.
EveLens is free, open source, and available on Windows, macOS, and Linux.
evelens.dev | github.com/aliacollins/evelens
Twenty years of community work. Seven weeks of rebuilding. One thread that wouldn't stop pulling.
Fly safe. o7
— Alia Collins
Appendix: Publishing Notes
26Suggested Schedule
| Part | When | Where |
|---|---|---|
| 1: One Thread Pulled Another | Launch week | evelens.dev, Reddit r/Eve |
| 2: 69 Static Events | 3 days later | evelens.dev, r/programming |
| 3: Surgery on a Beating Heart | 1 week | evelens.dev |
| 4: The Scheduler Was Broken | 10 days | evelens.dev, r/programming |
| 5: Zero ViewModels | 2 weeks | evelens.dev |
| 6: I Replaced the UI Framework | 2.5 weeks | evelens.dev, Hacker News |
| 7: Ship It | 3 weeks | evelens.dev, r/Eve, r/programming, HN |
The Hook
Part 1 gets them in the door. Everyone who's ever opened a codebase for "one small change" relates.
Parts 2-6 build credibility. Real numbers. Real commit hashes. Real decisions. Engineers verify. Non-engineers follow the narrative.
Part 7 is the one that goes wide. "I'm not an engineer. I used AI. Here's what I got wrong." Vulnerable, honest, useful. This is the one that gets shared beyond the EVE community.
28