nešto, the Nesto mascot

Structured PHP, wired by attributes.

Modules, dependency injection, guards, pipes, interceptors and an ORM, declared with native PHP 8 attributes. Structure that scales, in the language you already ship.

composer global require nesto/frameworknesto new my-apicd my-apiphp nesto start
src/Cats/CatsController.php
#[Controller('cats')]
final class CatsController
{
    public function __construct(private readonly CatsService $cats) {}

    #[Get('{id}')]
    public function findOne(#[Param('id')] int $id): Cat
    {
        return $this->cats->findOne($id);
    }

    #[Post]
    #[UseGuards(new AuthGuard('jwt'))]
    public function create(#[Body] CreateCatDto $dto): Cat
    {
        return $this->cats->create($dto);
    }
}

The building blocks

ModulesControllersProvidersGuards PipesInterceptorsException filtersMiddleware Lifecycle hooksDynamic modulesTesting moduleCLI

Request lifecycle

Every request takes the same path. Always in this order.

01 / 11An HTTP request arrives as a PSR-7 ServerRequest.

Batteries included

19 packages. One attribute away.

Official packages on PSR interfaces. Standalone, with no other framework underneath. Install what you use.

01

Core

Dependency injection

Constructor injection, custom providers, and request/transient scopes.

#[Injectable]

Config

config/*.php files and .env, read through a typed ConfigService.

new ConfigModule(isGlobal: true)
02

Input & output

Validation

Attribute rules on DTOs, with one error shape: messages grouped per field.

#[IsString, Length(min: 2)]

File uploads

Files are DTO fields, checked by their real content, size and count.

#[IsImage(maxSize: '5MB')]

Serialization

Expose, exclude and group fields on the way out.

#[Expose(groups: ['admin'])]
03

Data & files

ORM

Entities, repositories, relations, a query builder and migrations on PostgreSQL, MySQL, MariaDB and SQLite.

#[Entity('cats')]

File storage

Local, public and S3 disks, or your own driver, behind one API.

$file->store('avatars', 's3')

Cache & rate limiting

A PSR-16 cache interceptor and a throttler guard.

#[Throttle(10, 60)]
04

Security & API

Auth & JWT

Pluggable strategies, AuthGuard and #[CurrentUser].

#[UseGuards(new AuthGuard('jwt'))]

OpenAPI

Generates a Swagger UI from your controllers and DTOs, file uploads included.

#[ApiTags('cats')]
05

Background work

Events

An event emitter with wildcard listeners.

#[OnEvent('post.*')]

Task scheduling

Cron, interval and timeout jobs.

#[Cron('0 * * * *')]

Queues

Background jobs with processors and a worker command.

#[Processor('mail')]
06

Quality & production

Testing

Isolated testing modules and end-to-end HTTP requests, uploads included.

Test::createTestingModule([...])

Worker mode

FrankenPHP keeps the app and its database connections in memory.

php nesto start:prod

One feature, four files

A complete feature in one screen.

src/Cats/CatsModule.phpphp
#[Module(
    imports: [new OrmFeatureModule(Cat::class)],
    controllers: [CatsController::class],
    providers: [CatsService::class],
)]
final class CatsModule {}

CLI

Generate a whole resource.

One command writes the module, controller, service, DTOs, entity and test, then registers the module in AppModule.

start:prodroutesmigratemigrate:generatedb:seedadd config:publishstorage:linkqueue:workschedule:runmake:commandinfo
~/projects
$ nesto new my-api
$ cd my-api
$ php nesto g resource cats --orm
CREATE src/Cats/CatsModule.php
CREATE src/Cats/CatsController.php
CREATE src/Cats/CatsService.php
CREATE src/Cats/Dto/CreateCatDto.php
CREATE src/Cats/Dto/UpdateCatDto.php
CREATE src/Cats/Entities/Cat.php
CREATE tests/Cats/CatsControllerTest.php
UPDATE src/AppModule.php
$ php nesto start

Runs anywhere

FrankenPHP workerPHP-FPMPHP built-in serverRoadRunner workerDocker

Speaks 6 PSR standards

PSR-7 HTTP messagesPSR-11 ContainerPSR-15 Middleware PSR-3 LoggerPSR-16 CachePSR-14 Events
Construction drawing of nešto on a grid: a hexagon head, two round elephant ears, two pointed cat ears, a curled trunk and a four-point spark.

The mascot

Meet nešto.

Part elephant, part cat, all module. Every piece of the character stands for something.

Hexagon head
A module, the same shape as the logo.
Elephant ears and trunk
PHP's elePHPant.
Cat ears
The NestJS cat.
Spark
nešto means “something” in Croatian.

Build your first Nesto API in 10 minutes.

A blog API, start to finish: entities, JWT auth, validation, uploads, queues, OpenAPI and tests.