The workflow I’m trying
This is the first post in a series about building Dofousse Duels.
Dofousse Duels is a combat-only slice of Dofus, a tactical MMORPG I’ve played on and off for 20 years. Previous attempts to reimplement it stalled — once on the server side, once on the client side (I hate UI work). This time the scope is deliberately tiny: just combat, server and client, as a testbed for the game engine I’ve been writing.
I have a rule for my personal projects. I know I’ll abandon this one at some point, usually before it’s finished — I always do, and I’ve got dozens of half-finished side projects by now. I’m also always the only user, so nobody cares. The rule is that no matter what happens to the project, I have to have learned something new from it. That removes the frustration of not finishing things, of always starting something new. The thing I want to learn this time is AI tooling for developers. That’s what this blog is for.
The problem I’m actually trying to solve
Solo projects die when life happens. I drop them for weeks or months, come back, and the mental context is gone. The code still runs, the README still exists, but the why behind every design decision has evaporated. I spend two evenings re-reading my own repo trying to remember what I was doing, lose momentum, and set the project down again.
I think — and this is personal, no evidence — that “lack of time” is rarely what kills these projects. What kills them is the cost of re-entry.
So when I started Dofousse Duels, I decided to try an AI-first workflow with a specific bet: if I externalize enough of the mental context, re-entry gets cheap. Coming back after three months shouldn’t feel like archaeology.
What the spec phase actually looked like
Before writing a line of runtime code, I spent hours discussing specs with Claude. The output is a specs/ folder
with fifteen markdown files covering things like match lifecycle, identity, the SignalR hub, hidden information,
turn flow, contracts, and the client architecture. One concept per file.
Here’s what a spec actually looks like — top and tail of specs/identity.md, which is where the guest-account
decision I’m about to talk about ended up:
---
name: Identity
description: Guest-first account model with optional upgrade to a
credentialed account.
---
# Identity
Every user — even a first-time anonymous visitor — has a server-side
account record. A **guest** account is bound to a browser via a stable
cookie; an **upgraded** account additionally has login credentials
(email/password or OAuth). Upgrade does not migrate data; it attaches
credentials to the existing record, so guest-created characters,
replays, and history survive automatically.
[... guest model, upgrade flow, auth platform, reconciliation ...]
## Open questions
- Exact TTL for inactive guests. Lean 30 days.
- Whether to expose a one-time "recovery code" so guests can migrate
across browsers without upgrading. Leaning post-v1.
Every spec ends with an open-questions section when anything is still undecided. “Lean X” is the current default, not a commitment. Nothing gets silently deferred — if it’s open, it’s visible.
What surprised me was how much it felt like having a PM in the room. Not in a “tool that helps me plan” way — in a “someone points out what you’d have gotten wrong because you don’t know the domain, and pushes back when you’re about to over-scope” way.
Two flavours of this stood out.
Domain knowledge I don’t have. I’m not a game developer. I was designing the account system the way I’d design one for any web app — email, password, optional OAuth. Claude raised the guest-account mechanic: a full-fledged account without an email, so a first-time user can just click “play” and go. Standard in games, apparently. Would not have occurred to me. The actual identity spec (guest-first accounts, cookie reconciliation on reconnect, optional upgrade) is downstream of that one suggestion I wouldn’t have made on my own.
Scope discipline. Devs — or at least me specifically — are bad at scoping. A good PM is great at it; a solo developer with no constraints is, in my experience, the opposite. The specs process pushed back more than once on things I was about to over-build. The most honest example is the one that didn’t happen: solo-me would have sat down and designed a full content editor for the game before writing the first line of the game scene itself. I’m exaggerating a little, but not much. Having the spec conversation meant that instead of building features for a v1 that nobody has played yet, I kept having to answer “does v1 actually need this?” — and the answer was usually no.
Renaud, if you’re reading this: I’m not replacing you. A rubber duck that occasionally volunteers domain knowledge isn’t a PM. But on a project where I’d otherwise have no one pushing back, it’s not nothing, and it felt closer to working in a team than any solo project I’ve done before.
Moving to the roadmap
The specs answer how the system works. They don’t answer what am I doing about it right now. That’s what the
roadmap/ folder is for.
It’s organized around epics — coarse areas or milestones like contracts, identity, combat, replays, deployment.
Each epic is a subfolder with a README describing the goal and exit criteria, plus individual ticket files
underneath. Tickets carry frontmatter for status, for the specs they relate to, and for dependencies on other
tickets. There’s a status lifecycle (planned → in-progress → blocked → done); when a ticket flips to done the
file moves to a completed/ subfolder in the same commit, so the path itself encodes progress. One ticket per PR,
multiple PRs per ticket fine, no bundling.
The tree looks roughly like this:
roadmap/
├── README.md
└── epics/
└── E001-contracts-and-codegen/
├── README.md
├── T0001-rest-openapi-document-pipeline.md
├── T0002-signalr-dto-inclusion.md
├── T0003-typescript-type-generation.md
└── completed/
An epic README is mostly a dashboard pointing at its tickets:
---
id: E001
title: Contracts and TS codegen pipeline
status: planned
specs:
- specs/contracts.md
- specs/repo-layout.md
---
## Goal
Establish the OpenAPI Document as the common language between the C#
server and the TypeScript client...
## Tickets
- T0001 — REST OpenAPI document pipeline — `planned`
- T0002 — SignalR DTO inclusion in OpenAPI document — `planned`
- T0003 — TypeScript type generation from OpenAPI — `planned`
A ticket is a PM-style slice of functional outcome, not a scaffolding task. Here’s the top of
T0003-typescript-type-generation.md:
---
id: E001-T0003
title: TypeScript type generation from OpenAPI
status: planned
epic: E001
specs:
- specs/contracts.md
blocked-by:
- E001-T0001
---
## Goal
The client build consumes the OpenAPI file artifact produced by the
server's `dotnet build` and produces TypeScript type declarations
under `client/src/contracts/`, in both local development and CI.
The frontmatter is the system. A ticket links back to its epic, to the specs it references, and to any tickets it depends on. Claude follows those links to pull the right context without me narrating it each time.
I’m only a couple of tickets in, so I don’t have real opinions on the roadmap format yet. The separation of concerns is what I’m hoping will make the difference long-term: specs answer design questions, roadmap answers sequencing questions, and there’s a rule that if the two disagree, specs win on design and roadmap wins on sequencing.
Everything is a plain markdown file
Specs, roadmap, tickets — all of it lives in the repo as markdown. No JIRA, no Linear, no Notion.
The reason is that I want the tool to be as easy as possible for Claude to use. Reading context shouldn’t require network calls. Editing shouldn’t require an API wrapper. Keeping things fresh as work progresses shouldn’t depend on remembering to sync between systems. The stupidest option I could come up with was: a text file with a bit of structure (frontmatter, status conventions, file-layout conventions), checked in next to the code.
What I didn’t fully appreciate up front is how much the structure of the files matters on top of the file format. Each spec is one concept, on purpose. The roadmap README is a dashboard pointing at epics; each epic README is a dashboard pointing at tickets.
I’m not certain this is the right shape. What makes me think it’s working is that Claude spends much less time re-reading source files to reconstruct what things do. The summary that would otherwise get rebuilt in every session is already on disk. Pick up next session, same summary, no reconstruction.
The docs update with the code
It would be easy to read the above as “spec phase, then execution phase.” That’s not what’s happening. The specs and roadmap are not written once and left alone — they update in the same commits as the code they describe.
When a decision made during a ticket affects a spec, the spec is updated in the same PR. This has happened multiple times already — including while I was writing the initial CD pipeline, where implementation choices forced updates to the specs they touched. When a ticket spawns a follow-up, the follow-up becomes a new ticket in the same PR. I’ve set this up as a persistent instruction to Claude, so during any code session Claude prompts me about doc updates — I don’t have to remember to do it on my own.
A side benefit I’m hoping will pay off over time: when I review a PR, the doc diffs should act as a summary of what changed in my thinking. The code diff shows what moved; the spec diff shows why. Both land in the same review, which would mean I can push back on a design choice by pushing back on the spec that justifies it, instead of arguing about implementation details with no shared reference. Too early to say whether this holds up across many tickets, but the shape of it was already visible in the CD pipeline reviews.
What I’m uncertain about
Honest list, for future-me to revisit:
- Whether I’m over-specifying. Some of these specs are detailed for a solo project that may never ship.
- Whether the roadmap format will survive contact with implementation, or whether I’ll rip it up at the first serious friction.
- Whether the “PM in the room” feeling was real or was me pattern-matching onto something I wanted to be true.
- Whether the context I’m externalizing is actually the context I’ll need when I come back. Writing down what I think matters is not the same as writing down what future-me will wish I’d written down.
TODO for future me: edit this and answer my questions.
This is entry one. There will be more as things break.