Quick start: an explicit JSON route
This guide uses the Web scaffold, Engine, HTTP engine and Router together. Engine alone is not a complete application. Web requires PHP ^8.2, curl and json; its dependency tree adds requirements such as intl. Engine alone declares PHP ^8.1 and Server ^4. Do not replace Server 4 with Server 7 in this scaffold.
Create and inspect the application
Section titled “Create and inspect the application”composer create-project triangle/web my-appcd my-appcomposer check-platform-reqscomposer show --directcomposer show localzet/serverKeep the resulting composer.lock. A successful dependency resolution does not prove runtime compatibility: see compatibility notes. The old documentation’s port 88 is not the current Web default; config/server.php defaults to http://127.0.0.1:8000. An environment file can override it. Inspect SERVER_LISTEN in your own .env and keep it on loopback for local development. Never copy real credentials into examples.
Define the route
Section titled “Define the route”Replace config/route.php with:
<?php
declare(strict_types=1);
use Triangle\Request;use Triangle\Response;use Triangle\Router;
Router::get('/api/hello/{name}', static function (Request $request, string $name): Response { return responseJson(['message' => 'Hello, ' . $name]);});This file executes route registration; it must not return a configuration array. responseJson() returns a JSON response directly. response()->json() and Triangle\View\View::render() are not the API used by this source. The native scaffold maps app\controller to app/controller; preserve path/namespace case on Linux.
Local worker configuration
Section titled “Local worker configuration”In config/server.php, make the environment value explicitly numeric:
'count' => (int) env('SERVER_COUNT', 1),The reviewed scaffold passes the environment string through unchanged; with SERVER_COUNT=1 this can fail the typed Server helper. The isolated check uses this cast and disables the optional process monitor with config/process.php returning an empty array. It is a minimal route check, not verification of every background process or production setting.
Run and verify
Section titled “Run and verify”php master startIn another terminal:
curl -i http://127.0.0.1:8000/api/hello/ReaderThe route is intended to return HTTP 200, Content-Type: application/json and {"message":"Hello, Reader"}. Stop the foreground process with Ctrl+C. Reload PHP worker code after changes; a long-running worker does not reload every file per request.
Choosing a response helper
Section titled “Choosing a response helper”responseJson($data, $status, $headers)serializes the supplied data directly.response($data, $status)can wrap data instatus/data, add debug output, choose a view, and honorapp.http_always_200. It is not interchangeable with a raw JSON contract.view('index/view', ['name' => 'Triangle'])uses the configured view renderer. Do not assume aViewfacade exists.
Database-backed routes additionally need a configured database, migrations, model policy, input validation and authorization. A POST endpoint that simply calls User::create() is not a safe starter API. Those concerns are intentionally outside this minimal route.
Sources: Web scaffold, Engine response helpers, View helpers. Reviewed 2026-10-17. Web retains its own MIT license; component licenses are separate. New example: AGPL-3.0-or-later, Ivan Zorin / Localzet Group.