Last updated: May 30, 2026
Note: This roadmap is scoped specifically to the internal mechanics of the
outboardphp/frameworkpackage. For the high-level vision and phases of the entire Outboard ecosystem (including frontend integration and APIs), see the Ecosystem Roadmap in the project root.
This document describes what the outboardphp/framework package should grow into and in what order.
Outboard is intended to center on a PSR-15 middleware pipeline and the ADR (Action-Domain-Responder) paradigm. The framework package provides the reusable runtime and integration surface for that architecture.
At the moment, the framework package is still mostly scaffolding:
Outboard\Framework\Applicationis currently a placeholder invokable class.Outboard\Framework\ConfigProvideris currently a placeholder definition provider.- The basic skeleton still manually wires the container in
apps/basic-skeleton/public/index.php. - The skeleton's
App\ConfigProvideris also still a stub.
That is normal for this stage. The next goal is not to add lots of app features inside the framework package, but to establish the core mechanical flow.
The framework package should evolve into a small reusable kernel that can:
- assemble framework-owned definitions
- merge those definitions with app-provided definitions
- build or receive a container
- resolve the runtime services needed to handle a request
- run the middleware / dispatch pipeline
- return or emit a response
The basic skeleton should then become thinner:
- declare app definitions
- declare app routes and app services
- provide a minimal front controller
- hand off execution to the framework runtime
In other words, the skeleton should stop manually constructing core runtime pieces once the framework can own that bootstrap path.
Goal: Make the framework package responsible for reusable bootstrapping.
- Implement
Outboard\Framework\ConfigProvideras a real definition provider. - Decide how framework and app definition providers are combined.
- Standardize how the framework discovers or receives app-level definitions.
- Give
Outboard\Framework\Applicationa real bootstrap role instead of placeholder output. - Remove manual framework runtime construction from the skeleton wherever possible.
- a clear entry point for framework services
- a repeatable definition aggregation story
- a minimal but real application kernel contract
- tests that prove framework bootstrapping works without app-specific logic baked in
- the framework can combine framework and app definitions cleanly
- the skeleton no longer needs to know how core runtime services are built
- there is at least one end-to-end test that proves the boot path works
Goal: Establish the minimum reusable HTTP runtime in the framework package.
- adopt PSR-7, PSR-15, and PSR-17 dependencies in the framework package
- define how requests are created or received
- define middleware pipeline assembly and execution
- define how a response is produced and emitted
- keep the initial surface area small and explicit
- reusable request/response lifecycle support
- middleware pipeline assembly owned by the framework
- framework-level service definitions for HTTP runtime pieces
- tests for request handling and middleware ordering
- a request can enter the framework runtime and yield a response
- middleware can be registered without hardcoding app concerns into the framework
- framework tests cover the basic pipeline behavior
Goal: Add the first real application dispatch story.
- introduce routing in the framework package
- likely ship a Symfony Routing-based adapter first
- define how a matched route maps to an action
- define the minimum ADR workflow needed for the first vertical slice
- keep domain and responder implementations app-owned unless a generic abstraction is clearly reusable
- route matching integration
- route result handoff into action dispatch
- generic dispatcher behavior for request-to-action flow
- extension points for route params and action resolution
- one request can be routed to one app action and produce one response
- the framework owns the generic route-dispatch lifecycle
Goal: Add reusable seams, not hardcoded app choices.
- lifecycle events and optional Wake integration
- error handling strategy
- configuration conventions for optional packages
- framework-level interfaces or adapters for templating, logging, or other common concerns only where there is clear cross-app value
- stable hooks for extension
- reusable integration seams rather than one-off app decisions
- framework documentation for overriding defaults
- framework integrations remain optional and replaceable
The smallest worthwhile next slice is:
- make
Outboard\Framework\ConfigProvidera real provider of framework-owned definitions - make
Outboard\Framework\Applicationorchestrate the reusable bootstrap path - have the basic skeleton provide only app definitions and a tiny
public/index.php - prove the flow with one end-to-end path through the framework runtime
A good first acceptance target is:
- the skeleton front controller delegates to framework bootstrap
- framework and app definitions are combined in a standard way
- one app action can be resolved through the container
- one request can be handled without the skeleton needing to build the runtime manually
If implementation begins immediately, work in this order:
- Definition aggregation and bootstrap ownership
- Minimal HTTP runtime and middleware pipeline
- Router integration and first ADR dispatch path
- Error handling and lifecycle hooks
This order keeps the framework focused on reusable runtime value first and avoids building a rich skeleton on top of a runtime that is still undefined.