All guides

Create a Stage application

skyyware/stage v0.1.5

Build a PHP endpoint that returns JSON. This example uses Stage 0.1.5 and PHP 8.4 or a later PHP 8 release. Sources checked on 9 October 2026.

Install the framework

With PHP and Composer installed, run:

mkdir stage-app
cd stage-app
composer require skyyware/stage:^0.1.5
mkdir public

Composer downloads Stage from Packagist without a GitHub sign-in or a custom repository setting. Keep the generated composer.lock.

Add the endpoint

Create public/index.php:

<?php
declare(strict_types=1);

use Stage\Http\Application;
use Stage\Http\Response;
use Stage\Http\Route;

require dirname(__DIR__) . '/vendor/autoload.php';

(new Application(
	Route::get('/', fn () => Response::json(['hello' => 'world'])),
))->run();

From the application directory, start the local server:

php -S 127.0.0.1:8080 -t public public/index.php

Open http://127.0.0.1:8080. Expect status 200 and {"hello":"world"}. Press Ctrl+C in the terminal to stop the server. PHP's built-in server is for development. A public server must expose only public/.

Check a response without a server

Create check.php in the application directory:

<?php
declare(strict_types=1);

use Stage\Http\Application;
use Stage\Http\Request;
use Stage\Http\Response;
use Stage\Http\Route;

require __DIR__ . '/vendor/autoload.php';

$app = new Application(
	Route::get('/', fn () => Response::json(['hello' => 'world'])),
);
$response = $app->handle(new Request('GET', '/'));
if ($response->status !== 200 || $response->body !== '{"hello":"world"}') {
	throw new RuntimeException('Unexpected response.');
}
echo 'Response checked', PHP_EOL;

Run php check.php. Expect Response checked. handle() returns a response without sending headers or output. Use it to test your own routes, including rejected input and denied access.

Add your own test tools and scripts. Installing Stage does not add a composer check command to your application.

Sources