I was inspired to write this post after reading Making Video Games in 2025 (without an engine) by Noel Berry. While not a game developer myself, Noel’s piece resonated deeply with my web development experience. My interest was sparked after watching Datastar: a real-time SSE hypermedia framework, which got me excited about applying its principles to game development tooling.
Noel Berry’s core argument champions direct control, simplicity, and the strategic use of focused tools over lumbering, proprietary ‘do-everything’ engines. He values understanding his entire stack and sculpting tools precisely to his game’s needs.
I agree entirely. The allure of an engine promising to solve every problem comes with a hidden ‘complexity budget’ that drains productivity. However, coming from a web development background, I believe this philosophy can be pushed even further. What if the ‘no-engine’ path was about a paradigm shift enabled by a truly modern systems language for the game core and, surprisingly, some of the most robust architectural patterns from the web for tooling?
This is where a modern stack comes in: Zig for the game, and a deliberate choice between Zig or Go for the tooling backend, all orchestrated with a hypermedia framework like Datastar.
So, You Want to Ditch Your Engine and Actually Write Your Game in 2025?
The year is 2025. You’ve seen the engine licensing fiascos. You’ve felt the dread of a proprietary update nuking your project. You’ve waded through the 90% of features you don’t need. Many assume going ‘engineless’ means hand-crafting assembly by candlelight.
Contrary to popular belief, this path is about reclaiming control, simplicity, and joy. It’s more achievable and more fun than ever. Noel Berry perfectly captures this yearning:
I genuinely believe making games without a big ‘do everything’ engine can be easier, more fun, and often less overhead… I like knowing that in another two decades from now I will still be ableable to compile my game…
This is a pragmatic response to an industry layering complexity for complexity’s sake. But what’s the alternative when you want to ship a game?
The Zig Ascendancy: One Language for CPU and GPU
For the game itself—the part that needs maximum performance and direct hardware control—the choice is becoming clear: Zig.
For years, the game dev world accepted a painful trade-off: C++ for performance, or a higher-level language for productivity. Crucially, you always needed a separate shading language (GLSL/HLSL) for the GPU. Zig shatters this paradigm. Its ability to directly compile for the GPU is revolutionary. As detailed in Zig and GPUs, Zig can generate SPIR-V, PTX (NVIDIA), and AMDGCN (AMD) code.
Let that sink in. No more mental context-switching. Zig offers a unified front:
- Direct GPU Compilation: Write your vertex shaders, fragment shaders, and compute kernels in Zig. This is a monumental shift in game development workflow and cognitive overhead.
- Best-in-Class C Interoperability: Use crucial libraries like SDL3 or FMOD seamlessly.
comptimeSuperpowers: Process assets and compile shaders at compile time.- Integrated Build System: One tool,
zig build, to compile your game, C dependencies, and GPU kernels. - Unapologetic Control: You manage memory, control data layout, and get screaming performance. No hidden GC pauses, ever.
This is true Architectural Sympathy. You are working with the hardware. Go, for all its strengths, is not designed for this; it has no meaningful story for GPU programming. For the performance-critical game core, Zig is in a class of its own.
Tools of the Trade: Your Editor as a Web-Powered Control Panel
Noel Berry uses Dear ImGui, a solid choice. But for a sophisticated editor, I propose a different model: your editor is a lightweight, server-driven web application.
Enter Datastar, a hypermedia framework where the server is the single source of truth. It uses Server-Sent Events (SSE) to push UI updates (as HTML fragments) from a backend. The editor, built with simple HTML/CSS, receives these fragments and Datastar’s tiny runtime efficiently morphs them into the page.
The architectural beauty is that the state—the ‘source of truth’ for your editor—lives on the server. This brings us to the crucial decision: which language should power that server?
Choosing Your Tooling Backend: Go vs. Zig
This isn’t just a technical detail; it’s a core architectural philosophy choice. Both are excellent options, but they represent two different approaches to system design.
Option 1: Go — The Robust, Concurrent Service
Go is a phenomenal choice for a tooling backend, especially if you favor a clean separation of concerns. In fact, Datastar itself is written in Go, a testament to the language’s suitability for event-driven, networked applications.
The Philosophy: Your game is a highly-optimized Zig process. Your editor is a separate, robust Go service that communicates with the game.
Strengths:
- Concurrency is King: Go’s goroutines and channels are first-class primitives for handling many simultaneous events, perfect for a real-time editor that might be processing user input, asset changes, and game state updates concurrently.
- World-Class Networking: Go’s standard library for building HTTP servers is simple, powerful, and battle-tested.
- Separation of Concerns: The game can crash without taking down the editor, and vice versa. Your game logic remains pure and unconcerned with serving HTTP requests.
- Ecosystem: Go has a mature ecosystem for web services, making it easy to add features like a web-based asset browser or collaborative editing.
The code to stream real-time updates is astonishingly simple in Go:
// In your Go tool server:
func streamHandler(w http.ResponseWriter, r *http.Request) {
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
sse := datastar.NewSSE(w, r)
for {
select {
case <-r.Context().Done(): // Client disconnected
return
case <-ticker.C:
// ... logic to get state from the Zig game process ...
hexString := generateRandomColor()
frag := fmt.Sprintf(`<span id="feed" style="color:#%s;">%s</span>`, hexString, hexString)
sse.MergeFragments(frag)
}
}
}
The Trade-off: You need a communication layer (Inter-Process Communication or IPC) between your Go tool server and your Zig game. This could be gRPC, a simple TCP socket, or shared memory, but it’s an additional piece of infrastructure to design and maintain.
Option 2: Zig — The Tightly Integrated Powerhouse
Alternatively, you can build your tool server directly into your game process using Zig.
The Philosophy: Your game and editor are two facets of a single, unified application.
Strengths:
- Ultimate Integration: The tool server has direct, zero-overhead access to the game’s memory and state. There is no need for IPC.
- Locality of Behaviour (LoB): The Zig code that defines a game object can live right next to the Zig code that generates the HTML to edit it. This is a massive win for maintainability.
- Single Language: Your entire project—game core, shaders, and tooling—is in one language, reducing cognitive load for the developer.
- Simplicity of State: There is only one source of truth, and your editor reads from it directly.
The Datastar Zig SDK makes this seamless:
// In your Zig application, which is also an HTTP server:
var sse = try datastar.ServerSentEventGenerator.init(response);
// User clicks "Create New Enemy" in the editor UI:
// 1. Create the enemy directly in your game's data structures.
const newEnemy = myGame.createEnemy();
// 2. Send an HTML fragment to the editor UI.
try sse.mergeFragments(
\\<div id="enemy-{d}" class="enemy-card">...</div>
, .{ newEnemy.id });
The Trade-off: Your game process is now also a web server. This couples the stability of your editor to the stability of your game. A crash in one brings down both. It also means your core game loop must coexist with a web server event loop.
The Complexity Budget Revisited
So, is this simpler?
- Big Engine: Massive, opaque complexity you must learn and fight.
- No-Engine Stack: A series of deliberate choices. You trade the ‘one-size-fits-all’ complexity of an engine for the ‘understandable-and-chosen’ complexity of your own stack.
Your decision on the tooling backend is a perfect example:
- Choose Go if your complexity budget prioritizes service isolation and leveraging a best-in-class networking language, at the cost of managing IPC.
- Choose Zig if your budget prioritizes code colocation and zero-overhead state access, at the cost of a monolithic process.
The ‘simplicity’ here is the coherence of the stack and your ability to reason about it from top to bottom.
So, Should You Ditch Your Engine for This Future?
As Noel wisely concludes: ‘If it sounds fun.’
If the idea of writing your game logic and its shaders in a powerful systems language like Zig excites you; if the thought of crafting bespoke tools where a Go or Zig backend seamlessly drives a web frontend sounds intriguing; if you crave control, simplicity, and the satisfaction of building something truly your own—then yes. Absolutely, yes.
The path of ‘no engine’ in 2025 isn’t about being a Luddite. It’s about being a craftsman. It’s about choosing Zig for its unparalleled control over the hardware and then making a conscious architectural decision about your tooling that best fits your philosophy. It’s about building games that are lean, performant, maintainable, and entirely yours.