Why Weft is deliberately not a framework
Weft ships with a rejection list instead of a roadmap: no ORM, no DI container, no admin panel. What that decision buys a content-first site engine, and what it costs.
Weft is a PHP 8.4 engine for content-first sites: landing pages, portfolios, product and documentation sites. The part of it I want to write about is not a feature. It is the list of things it refuses to become.
Weft's roadmap file has a section most roadmaps don't: rejected directions. No ORM. No DI container. No admin panel. These are not gaps waiting for a contributor with free time. They are decisions, recorded so that future-me cannot quietly reverse them on a motivated afternoon.
The bar for an engine feature
Every small site re-solves the same layer before it can launch: clean URLs, locale prefixes, a correct head section, a sitemap, spam-resistant forms, request tracing, asset hashing. None of that is why the site exists. All of it has to work anyway.
That layer is what Weft is. The bar for putting something into the engine is blunt: most content sites need it. Convention routing passes: pages/about.php serves /about, and a [slug] file serves the dynamic segment, so there is no route table to maintain. SEO output passes: title templates, canonical, Open Graph, hreflang and JSON-LD come from config with per-page overrides, and the engine generates /sitemap.xml and /robots.txt itself. Form protection passes, because every contact form on the internet gets spammed.
An ORM does not pass. A content site barely queries anything; Weft ships a thin PDO wrapper and stops. A DI container does not pass either: static facades are the intended design, because on a site of a handful of pages, container indirection costs more in ceremony than it returns in flexibility. And an admin panel would turn an engine into a CMS, which is a different product with different problems. If your project fails the bar in the other direction, because it genuinely needs those things, you need a framework, and PHP has good ones.
The corollary of a strict bar is that optional features must be safe to ignore. Everything optional in Weft is a flag, and "off" is a real state, not an error path: Cache::remember() still executes its callback through a null store when caching is disabled, reCAPTCHA verification passes safely when it is turned off, i18n is off by default and leaves no trace in your URLs until you enable it. Optionality lives inside the engine, so it never leaks into your pages as conditional code.
The documentation is the example, and the example is a site
Weft's example/ directory is a complete working site, and that site is the documentation. Every page describing the engine is served by the engine it describes. The routing chapter is routed by convention routing. The SEO chapter renders its own head section the way it tells you to.
I like this arrangement for an unsentimental reason: it removes the option of documentation drift. A separate docs site can describe a feature that quietly broke three versions ago. Here, if a described feature breaks, the page describing it breaks with it.
Where it actually stands
v0.1.1 is the current release, an alpha. The source is public under MIT, installable via Composer as golovanov/weft, with a 160-test PHPUnit suite and CI running from the first tag. The API may change before 1.0.
The first production site running on Weft is the one you are reading this on: golovanov.dev. The engine's first real consumer is the person with the least patience for its flaws, which is the position I want to be in for an alpha: every rough edge lands on my desk first.
If you want to judge the routing convention, the test takes minutes: install it, add one page file, load the URL.