You know the drill. The client's content is aircraft parts, or recipes, or a course catalog; the platform's content is posts, or channels, or sections, or collections, depending on which decade and which vendor got to you first. The distance between those two things is where the whole job lives. You've closed that gap with a template parse order you fully understood for one glorious afternoon in 2011. You've closed it with the field that holds more than one of something, reinvented under a new name every few years so the ecosystem can fall in love with it again. And somewhere around year two you notice the actual content model doesn't live in the CMS at all; it lives in the add-ons and glue code holding the platform's idea of content at arm's length from the client's.
None of those platforms were wrong. Every one of them was almost enough, and almost enough is the most dangerous amount of enough; it's the amount that keeps you customizing instead of questioning.
After twenty-plus years of closing that same gap in different vendors' vocabularies, across sites, e-commerce builds, and custom CMSs, I got tired of having the same argument with different software. So I built AdAstra.
What it is
The part I'm most opinionated about is the split between structure and behavior.
Structure (fields, layouts, statuses) is defined at runtime, in the admin, where it belongs. Behavior (validation, lifecycle hooks, the business logic that makes a blog post different from an aircraft part) lives in versioned PHP classes bound to entry types, where it belongs. Structure belongs to the admin; behavior belongs to the repo; the entry type is the seam. Anyone who has shipped business logic inside a template because there was nowhere else to put it knows exactly why this layer exists. It deserves its own post, and it's getting one.
Everything else follows from that. AdAstra is a content platform on Laravel 12: you define entry groups, entry types, field layouts, statuses, and behaviors, and authoring, routing, Twig templates, the REST API, publishing workflow, and admin are all generated against that definition. Not pages-first, not posts-first; model-first. The model is the input, not something you reverse-engineer out of a page hierarchy six months in.
If you spent formative years in a channels-and-fields world, or a sections-and-entry-types one, the shape will feel familiar, and that's on purpose; those paradigms got a lot right. What changed is where the line sits. Hierarchy, relationships, statuses, and media are core concerns, with the same standing as entries themselves.
The question most CMSs make you ask is "how do I make my content fit this thing?" AdAstra exists so the question can be "what does my content actually look like?", which was always the right question; the software just kept interrupting.
The docs go deep on the architecture if you want the full tour.
The backwards part
Here's what's unusual about this announcement, and it's deliberate: this is the first real public word about AdAstra, and the software is already on its second alpha. Alpha 1 went out June 29 to an audience of, roughly, one LinkedIn post and a couple dozen direct messages to friends who dev. Alpha 2 shipped July 17.
Most product announcements are a promise. This one's a changelog.
What Alpha 2 did
The headline change is structural: everything that makes AdAstra AdAstra now lives in a standalone Composer package, adastra/core, with the repo root reduced to a thin Laravel host application that pulls the platform in as a dependency.
If you've been doing PHP long enough, you know why this matters and why it happened now. Splitting a codebase into packages is something every project plans to do "later," and later is the most permanent word in software. Five years on, the blog module is holding hands with the invoicing module through a global helper function, and the split that would have cost a weekend now costs a rewrite (which is why it never happens). AdAstra did the split at alpha, while it's cheap. It's also the foundation for where the platform is going, which I'll get to in the section about money.
The rest of Alpha 2 is what alphas are actually for: finding the gap between how a system was designed to work and how it turns out it works, then closing it. A sampling:
- Personal access tokens no longer take a victory lap through the URL. Tokens were being flashed into a session redirect string; they now go where secrets go, which is nowhere visible.
Api\v1\User::update()now enforces its permission check. It always had one. It just, in the grand tradition of security theater, wasn't consulting it.- Entry Tree request fields that were validated and then silently ignored are now read downstream. The validator was doing its job; nobody was reading its report.
field_valuesgrew proper indexes, because an EAV-adjacent table without indexes is less a schema than a threat.
Alpha 2 also added php artisan adastra:doctor, a health report for your installation. It verifies that the classes your database claims to use still exist, and generally checks for the drift that accumulates in any system where content structure is defined at runtime. It is read-only by design, because a doctor that operates without asking is called a defendant. The output is secrets-safe, so you can paste it straight into a GitHub issue.
The full list is in the changelog, including BotBlock learning that HTTP has verbs other than POST.
The media layer, which exists, with an asterisk
The native media layer is in the system now: first-party media libraries, image transformations, and storage handling, built into the platform itself. (Spatie's MediaLibrary carried the early builds and it's an excellent package; a content platform just needs to own its media layer the way it owns its entries.)
It also has known issues, and so do the field types that lean on it, and I'm telling you that in the announcement instead of letting you discover it in a bug report, because that's the deal with an alpha. The fixes are planned for Alpha 3, or 4, or possibly 5, depending on how deep the rabbit hole goes once we're down it; anyone who gives you a confident single-version estimate for "fix the media edge cases" is quoting you a number they made up. Kick the tires, and when it does something strange, that's exactly the feedback these releases are for.
What's next
Media and field type fixes first; that's the near-term work. Behind that, here's the roadmap for core, undated, because you just watched me refuse to estimate the media fixes:
- First-class SEO with dynamic JSON Schema. The platform already knows your content model; it should be the thing emitting meta and structured data that actually matches that model, instead of a plugin guessing at it from the outside.
- Localization. Content in more than one language, without buying the privilege.
- Queued Behaviors. Long-running content operations go through the queue, where they belong, instead of through a request that times out at the worst possible moment.
- Many-to-many Behaviors. Entry types that compose several behaviors instead of marrying one.
- Keyword search. Weighted, index-backed, built in.
Every item on that list ships in core. A few of them, you may notice, have historically been somebody's commercial add-on; here they're just features.
The honest section
Here's the direction, stated plainly, because if you're going to spend an evening evaluating an alpha, you've earned plain statements about where it's headed.
AdAstra is heading toward a core-plus-modules architecture. The package extraction above is step one; it's the seam. Some first-party modules will be commercial. This project needs to fund its own development, and I'd rather tell you that in the very first announcement than surprise you at 1.0; we've all been on the receiving end of that announcement, and we all still remember the vendor's name.
And because the opening of this post would be hypocrisy otherwise, here's the line I'll draw right now: the content model is not a monetization pocket. Hierarchy, relationships, statuses, media, and everything on the roadmap above; that's core, full stop. The commercial modules are the things that are separate products on their own terms. E-commerce is the obvious eventual example, and eventual is doing real work in that sentence; when it exists, it'll be a module because it's a different product. Nothing in core gets held hostage to it.
What I have not decided is the final licensing for the core itself. Right now the alpha ships under an evaluation license. The long-term model gets settled before beta, and it's exactly the kind of thing alpha feedback should shape. If you have opinions about how a free core should be licensed, I want them. The question is open, and open in the way that means your answer could move it.
Try it
Grab Alpha 2, run adastra:doctor against it, and break things; breaking things is the whole point of the exercise. Bugs go to GitHub issues. Opinions about what belongs in core go there too.
The docs live here. The full changelog is here. And Alpha 3 is closer than the version number suggests.