At some point AdAstra just started working. Was out of fucking nowhere, too, man. Content saved, routes resolved, the admin panel rendered, the thing did the things I thought it was supposed to do. I'd built a working and functional CMS, and I want to tell you I felt triumphant, but mostly I felt the floor drop out, because I'd just learned the thing we all (re)learn the hard way every single time a new publishable program is "complete".
The hard part is next: which is everything that has to be true around the code before you can put it in front of somebody whose opinion you actually care about. That's the part nobody puts in the tutorial. You finish the feature, you get the green checkmark, and then you look up and realize there's a second pile of work between you and "release" that's bigger than the feature was.
So, for months, the question had been "does AdAstra work," which is a question code can answer with little cost. You run it, you watch it, you fix what breaks, you run it again, you fix it again, and you watch it (again). It's a satisfying loop because it actually ends; there's a green checkmark waiting at the bottom of it. Now it was a different, worse one: am I comfortable asking another developer to burn an afternoon evaluating this?
Those aren't the same question, and the gap between them is where basically all of my work lives now. Almost none of it produces a feature anybody can see. Nobody's going to install AdAstra and go "ah, the release process is repeatable now." What it produces instead is an answer to whether the project deserves somebody else's time. That turns out to be the only question that matters before an alpha, and it's not a coding question.
Alpha Is an Excuse for Chaos, Not for Carelessness
Let me be clear about what an AdAstra alpha is going to be, because I've watched people soften this and I think the softening is a lie.
The APIs will change. The schemas will change. Features that exist today might be gone in the next release, not deprecated, gone. Names will change, because I'll pick a name for something, live with it for two weeks, and realize it was wrong. Decisions I'm confident about right now, today, are absolutely going to get reversed. There's a real chance that upgrading between two alpha releases won't be an upgrade at all; it'll be "drop the database and install again." Backward compatibility isn't on the table. I'm not even going to pretend it is.
This isn't a bug in the plan. This is the plan. The whole reason to ship an alpha instead of sitting on the code for another year is to find the architectural mistakes while they're still cheap to fix, and you can't fix them cheaply once you've promised forty people that the content_blocks table will keep its shape forever. Premature stability is how you end up carrying a bad decision for the life of the project, because by then ripping it out would break too many people. This early, stability is a cost wearing a virtue's clothes.
So yeah. AdAstra alpha might need a fresh install next week. It might need another one the week after that. If that makes the project sound unserious, sit with it a second longer, because I think it does the exact opposite.
Alpha is permission to be wrong. It's not permission to be careless. Those two get mashed together constantly, and that's where alphas go to die. The goal right now isn't stability. It's disciplined instability: the architecture is allowed to move, violently, but every move is deliberate, documented, and explained. The chaos is the point. The carelessness isn't invited.
The Audience Isn't Who You Think
Here's the thing that reorganized my whole sense of what "ready" even means. The first people to install an alpha CMS aren't the people looking for a CMS.
Nobody picking a platform for their next production site is going to reach for something labeled alpha, and of course they shouldn't. The person who installs AdAstra in the next few months is a developer curious enough to install an alpha CMS for the sport of it. That's a specific animal, and it sizes up a project in a specific way.
They're going to read the source. They're going to scroll the commit history and quietly form an opinion about me from it. They'll look at the tests, and then, because looking at tests isn't enough, they'll look at the coverage. They'll open composer.json and judge my dependency choices. They'll read the changelog, click into the issues, glance at CI, check whether there's any static analysis, and reconstruct the architecture from the folder structure before they've created a single piece of content.
The repository isn't the packaging around the product. For this crowd, the repository is the product they're evaluating. The admin panel is almost beside the point; they might never get far enough to care about it. What they're really deciding is whether the person behind the project knows what they're doing, and every file in the repo is evidence in that trial. Once that clicks, "ready for alpha" stops meaning "the features work" and starts meaning "the evidence is in place."
Documentation Is a Form of Architecture Review
Docs shouldn't show up after people start asking questions. If they show up then, they show up as a string of apologies.
There's the obvious list of stuff to document, and I'm doing the obvious list: installation, configuration, core concepts, the architecture, the CLI commands, the APIs, the extension points, troubleshooting, and migration notes when a release earns them. That's table stakes and I won't pretend it's interesting.
What's interesting is what writing the docs does to the thing you're documenting. Writing down how a subsystem works is the fastest architecture review I've ever run on myself. You can't describe a concept in prose without being forced to name it, and naming it drags up every question you were quietly dodging: is this abstraction actually one thing, or two things I glued together? Is this term consistent with the term three files over? Does this assumption survive being said out loud? The doc interrogates the design.
And there's a tell that never lies. If explaining a feature takes three pages of caveats, the problem isn't the docs. The problem is the feature. The prose is just the first thing honest enough to say so.
Tests Are Evidence, PHPStan Is a Different Kind
Coverage matters, but the percentage isn't the point, and chasing the percentage is how you end up with tests that assert getters return what you set. The point of the suite is evidence: evidence that AdAstra behaves the way I say it does, that the failure states fail the way I claim, that the edge case I wrote up in the docs is a real thing the code actually handles.
There's a contradiction here that took me a while to make peace with. I'm writing PHPUnit tests, carefully, for code I fully expect to delete. That looks like throwing effort straight into a fire. It's the opposite. The tests are the reason I'm allowed to be aggressive with the architecture. When I decide the whole routing layer was a mistake, the suite is what tells me, in seconds, whether the replacement kept the behavior that mattered. The more unstable I let the architecture be, the more that automated verification is worth. Instability and testing aren't at odds; the testing is what pays for the instability.
Then there's PHPStan, which hands me a kind of confidence tests just can't. It finds problems no test I'd have thought to write was ever going to reach. Running PHPStan cranked up on alpha code, code I'm about to refactor over and over, isn't gold-plating; it's the difference between refactoring with the lights on and refactoring by feel. Tests and static analysis don't replace each other. They fail in different directions, which is exactly why I want both.
Communicating Change on Purpose
Using Semantic Versioning during an alpha isn't a promise of stability. Given everything above, that'd be a weird promise to make. It's a way to communicate change on purpose instead of by accident.
There's this widespread belief that 0.0.x means the numbers are decorative, that anything goes and the version is just a vibe. I don't want to run AdAstra that way. Even in 0.0.x, a version number can carry information: this release changed something you build against, this one didn't, this one's going to make you reinstall. The number is a message, and I'd rather send a deliberate one.
The expectations shift by stage, and I want the shift itself to be readable. During alpha, the architecture can break and a fresh install might be the upgrade path; getting the architecture right beats compatibility, full stop. In beta, the architecture starts becoming a promise, breaking changes go from routine to rare, and upgrade paths start to matter a lot. At 1.0, compatibility becomes part of the product itself, the thing you're allowed to make decisions around, because the version number finally means what version numbers are supposed to mean. Alpha instability and predictable communication aren't opposites. I can tell you exactly how unreliable this is going to be, and that's its own kind of reliability.
Developer Experience Starts Before the Admin Panel
For an early alpha user, the first experience of AdAstra almost certainly isn't the control panel. It's the install. Then the configuration. Then the command line. Then, inevitably, an error message when something goes wrong, because something always goes wrong at this stage and I'd be lying to plan otherwise.
So developer experience, for this crowd, is the install flow and the sensible defaults and how the CLI feels to use. It's diagnostics that point at the actual problem, config validation that fails loudly and early, exceptions that say something a human can act on instead of leaking a stack trace from four layers down. It's logging, predictable conventions, and troubleshooting docs for the moment the error message wasn't enough. None of that makes a screenshot worth putting on a landing page. All of it decides whether the developer closes the terminal annoyed or intrigued, and that happens long before they ever lay eyes on the admin UI.
Not Cannibalizing the Community That Got Me Here
AdAstra doesn't exist in a vacuum, and I'm not going to pretend it sprang out of nowhere. My career runs through ExpressionEngine, Craft, WordPress, and a pile of other systems, and ExpressionEngine especially isn't just another row in some competitive comparison matrix. I've spent years running mithra62 in that world, building products for it and doing client work on top of it. It's a community I've been part of for years, professional relationships, clients, products I built and sold, actual revenue, actual opportunities. A big chunk of my career, in other words. AdAstra is the thing I build in the hours that are left when the client work is done, which is worth saying plainly, because it's exactly why I can't afford for any of those hours to go to careless mistakes I could have caught the first time.
I've got no interest in rewriting that history to make room for a new project. I don't want to spin up a story about how ExpressionEngine failed everybody so AdAstra can ride in as the rescue. I don't need anyone to quit ExpressionEngine for AdAstra to be worth building. That framing is cheap, and it's also a lie, and the people I most want to reach are exactly the ones who'd see straight through it.
At the same time, pretending the products don't overlap would be its own dishonesty. Of course they overlap. They're both content management systems; they compete for some of the same attention and some of the same projects. The competition is real. It just doesn't require antagonism. AdAstra should earn its adoption on what it actually is, not by convincing someone that a platform and a community that served them well for a decade secretly let them down. Respect and competition are allowed in the same room. Pretending the markets don't touch isn't respect; it's just bad faith with better manners.
What Alpha Actually Promises
I don't want AdAstra to have a good reputation; I want AdAstra to have a reputation that's load bearing
If someone says "AdAstra seems well engineered," I don't want that resting on my say-so. I want the honest answer to be: don't take my word for it. Look at the tests. Look at the coverage. Run PHPStan yourself. Read the docs, the release history, the changelog, the issues, the source, the architectural decisions, the way breaking changes get announced. The whole reason I'm putting all that evidence in place is so engineering quality becomes something a stranger can verify without trusting me at all. Brand says I'm serious. Evidence lets somebody check.
So here's the actual contract. AdAstra Alpha does not promise stability, backward compatibility, painless upgrades, complete features, frozen APIs, frozen schemas, or production readiness. It promises none of that, and I'm saying so plainly instead of burying it, because the plainness is the credibility. What it does promise is intentional engineering, documented behavior, tested behavior, static analysis, breaking changes announced instead of sprung, releases you can actually understand, and serious attention to quality. AdAstra Alpha is expected to break. Sometimes it'll break badly. It should never feel careless. The openness about the first part is what makes the second part believable.
I'm also sure there's stuff I haven't thought of. This is my first time releasing this particular kind of project, and there's a whole category of concerns I know exist without yet knowing where they belong: a security disclosure policy, contribution guidelines, governance, issue templates, support expectations, a dependency policy, a deprecation policy, release provenance, a long-term compatibility policy. Some of those are alpha concerns. Some belong to beta, or to 1.0, or to a version of this project that has users I haven't met yet. Part of the work is figuring out which is which, instead of importing every process a mature project has just because it's mature. Cargo-culting governance onto a project with three users is its own kind of unserious.
Earning the Right to Release It
Releasing AdAstra Alpha means asking other developers for something genuinely valuable, and it's worth naming what that is instead of waving past it. Somebody has to install it. Read the docs. Understand the abstractions I picked. Hit the bug. Work out whether it's even a bug or whether they're holding it wrong. Write up what happened. Maybe open an issue. Maybe read the source to figure out what I meant. Maybe tell me the whole approach is wrong and here's a better one.
Alpha means I'm flat-out asking those people to help me find the places where I'm wrong. That's the deal, and it's a good deal, but it comes with an obligation on my side. My job is to make sure their time goes to the mistakes I couldn't reasonably have caught, not the ones I could've caught by spending an hour with my own test suite. Their time is scarce and so is mine, since AdAstra has to share me with a business and its clients, and that's the whole reason the discipline has to be deliberate rather than something I promise to get to later.
AdAstra Alpha is going to break. That's what the label's for, and I'm not going to apologize for it. What I refuse to let it feel is careless. If I'm asking another developer to spend their afternoon finding the places where I got it wrong, the least I can do is show I already spent mine looking.