Small, independent PSR packages for PHP. Use one, or all of them together.
Solo is not a framework. Each package does one job: a router, a container, request DTOs, a validator, repositories, a logger. They meet at PSR interfaces, and at solophp/contracts where PSR has none, so you can take one package into any project or replace one with another implementation. Two starter applications show how they fit together.
Website · Getting started · Packages · Packagist
Both starters need PHP 8.4 and Composer. They include tests and are set up for PHPUnit, PHPStan at level max and PSR-12.
Skeleton is a ready-to-run JSON API with one CRUD module, request validation, SQLite, error handling, logging and tests.
- Create the project with
composer create-project solophp/skeleton my-app. - Enter the project directory with
cd my-app. - Start the API with
composer serve.
Inertia Svelte Skeleton combines server-side routing and controllers with an Inertia.js 3 and Svelte 5 frontend. It also needs Node.js.
Create the project with composer create-project solophp/inertia-svelte-skeleton my-app.
Every package runs on PHP 8.3 or later, except Container, which needs 8.4.
| Package | What it does | Docs | Latest version |
|---|---|---|---|
| HTTP kernel | |||
| solophp/application | PSR-15 kernel: service providers, a middleware pipeline, routing and a route cache | Docs | |
| solophp/router | Routes, groups and parameter patterns, compiled for matching; URLs built from route names | Docs | |
| solophp/container | PSR-11 container with autowiring, interface binding and lazy services | Docs | |
| solophp/http-emitter | Sends a PSR-7 response: status line, headers and a streamed body | README | |
| solophp/contracts | The interfaces the packages share where PSR has none | README | |
| Input | |||
| solophp/input | Typed, immutable request DTOs, validated, cast and processed by attributes | Docs | |
| solophp/validator | Rule strings compiled once, one structured error per field | Docs | |
| Data | |||
| solophp/repository | Typed table repositories over Doctrine DBAL, with translations, batch-loaded relations, stable pages and transactions | Docs | |
| solophp/cache | PSR-16 cache with file and Redis adapters: atomic file writes, isolated Redis namespaces and typed values | Docs | |
| Infrastructure | |||
| solophp/logger | PSR-3 logger for files shared across processes and for standard error, in line, JSON or logfmt | Docs | |
| solophp/dotenv | Strict .env loader: layered files, server variables first, all-or-nothing loading and typed accessors |
Docs | |
| solophp/event-dispatcher | PSR-14 event dispatcher with priorities, subscribers, listeners matched by class or interface, and stoppable events | Docs | |
| solophp/job-queue | Database-backed job queue: leased claims with ownership tokens, per-job retry policies, a long-running worker | Docs | |
| solophp/rate-limiter | Atomic per-key rate limits: fixed or renewable windows in Redis, with an in-memory twin for tests | README | |
| solophp/tokens | Tokens for reset links, invitations and sessions: random secrets stored only as hashes, in Redis or in memory | Docs | |
| solophp/http-client | Immutable PSR-18 client on Guzzle: safe retries, credentials bound to their origin and redacted logs | Docs | |
| solophp/image | Immutable GD images: EXIF orientation, bounded resizing, JPEG, PNG and WebP encoding, and smaller-only optimization | Docs | |
| Frontend | |||
| solophp/inertia | Inertia.js 3 server adapter for PSR-7 and PSR-15: partial reloads, deferred props, flash data, SSR, Precognition | Docs | |
| solophp/vite | Vite without a framework: the tags that load entries from the dev server or the build manifest, an asset version and a Twig function | README | |
Archived repositories are no longer maintained; their replacements are listed under Legacy.


