Tempest 1.0
Tempest's first stable release
by Brent on June 27, 2025After almost 2 years and 656 merged pull requests by 59 contributors, it is finally time to tag the first release of Tempest. In case you don't know: Tempest is a framework for web and console application development. It's community-driven, embraces modern PHP, gets out of your way, and dares to think outside the box. There is so much to tell about Tempest, but I think code says more than words, so let me share a few highlights that I personally am excited about.
A truly decoupled ORM; this is what model classes look like in Tempest:
use Tempest\Validation\Rules\Length; use App\Author; final class Book { #[Length(min: 1, max: 120)] public string $title; public ?Author $author = null; /** @var \App\Chapter[] */ public array $chapters = []; } $book = query(Book::class) ->select() ->with('chapters', 'author') ->where('id = ?', $id) ->first();
A powerful templating engine; which builds on top of the OG-templating engine of all time — HTML:
<x-base :title="$this->seo->title"> <ul> <li :foreach="$this->books as $book"> {{ $book->title }} <span :if="$this->showDate($book)"> <x-tag> {{ $book->publishedAt }} </x-tag> </span> </li> </ul> </x-base>
Reimagined console applications; making console programming with PHP super intuitive:
final readonly class BooksCommand { use HasConsole; public function __construct( private BookRepository $repository, ) {} #[ConsoleCommand] public function find(): void { $book = $this->search( 'Find your book', $this->repository->find(...), ); } #[ConsoleCommand(middleware: [CautionMiddleware::class])] public function delete(string $title, bool $verbose = false): void { /* … */ } }
Discovery; which makes Tempest truly understand your code — no handholding required:
final class ConsoleCommandDiscovery implements Discovery { use IsDiscovery; public function __construct( private readonly ConsoleConfig $consoleConfig, ) {} public function discover(DiscoveryLocation $location, ClassReflector $class): void { foreach ($class->getPublicMethods() as $method) { if ($consoleCommand = $method->getAttribute(ConsoleCommand::class)) { $this->discoveryItems->add($location, [$method, $consoleCommand]); } } } public function apply(): void { foreach ($this->discoveryItems as [$method, $consoleCommand]) { $this->consoleConfig->addCommand($method, $consoleCommand); } } }
Or what about the mapper, command bus, events, logging, caching, localization, scheduling, validation, and even more.
There is a lot to tell about Tempest, and honestly, I'm so proud of what a small but very talented community has managed to achieve. When I started Tempest 2 years ago, the goal was for it to be an educational project, nothing more. But people stepped in. They liked the direction of this framework so much, eventually leading to where we are today.
And you might wonder: where does Tempest fit in, in an age where we have mature frameworks like Symfony and Laravel? Well: tagging 1.0 is only the beginning, and there is so much more to be done. At the same time, so many people have tried Tempest and said they like it a lot. It's simple, modern, intuitive, there's no legacy to be dealt with. Developers like Tempest.
I remember the first Reddit posts announcing Laravel, more than a decade ago; people were so skeptical of something new. And yet, see where Laravel is today. I believe there's room for Tempest to continue to grow, and I would say this is the perfect time to get started with it.
If you're ready to give it a try, head over to the docs, and join our Discord server to get started!