Search by

kipchak / starter

meezaan

Kipchak API Development Kit (ADK) Starter Project

Package info

github.com/kipchak-dev/starter

Homepage

Type:project

pkg:composer/kipchak/starter

Statistics

Installs: 26

Dependents: 0

Suggesters: 0

Stars: 0

4.1 2026-11-03 10:52 UTC

README

Kipchak

Kipchak Starter

The starter project for Kipchak, a PHP API Development Kit built on Slim Framework 4 and run on FrankenPHP in worker mode. It runs on PHP 8.4 and 8.5.

It contains one versioned resource, with its route, controller, DTO and model, an OpenAPI document generated from the code, a health check and tests. Nothing else is installed: add the drivers and middleware your API needs.

Documentation: https://kipchak.dev

Upgrading an existing project? See the upgrade guide.

Create a project

With PHP 8.4 or later and Composer:

composer create-project kipchak/starter my-api
cd my-api
docker compose up --watch

With Docker alone:

docker run --rm -u "$(id -u):$(id -g)" -v "$PWD":/app -w /app composer create-project kipchak/starter my-api
cd my-api
docker compose up --watch

The API is then on http://localhost:8080. --watch restarts the worker when a file changes. To use another port, start it with PORT=8081 docker compose up --watch.

Request Response
GET /v1/sultans Every sultan
GET /v1/sultans/4 One sultan; an unknown ID returns a 404
GET /openapi.json The OpenAPI document, generated from the code
GET /status A health check

Project structure

├── api/
│   ├── Controllers/          # Request handlers, versioned under v1/, v2/ and so on
│   ├── DataTransferObjects/  # The API contract: one DTO per shape of data, versioned with the controllers
│   ├── Middlewares/          # Middleware of your own
│   ├── Models/               # Business logic
│   ├── OpenApi/              # The top of the OpenAPI document: title, version, servers, shared responses
│   └── Utils/                # Code shared across the API
├── bin/openapi               # Writes the OpenAPI document to a file
├── config/                   # One PHP file per driver or middleware, returning an array
├── drivers/drivers.php       # The drivers the API initialises, in order
├── middlewares/middlewares.php # Middleware applied to every request
├── routes/                   # Route files, loaded at boot and versioned by folder
├── html/
│   ├── index.php             # FrankenPHP worker-mode entry point
│   └── index.nonworker.php   # Entry point without worker mode
├── tests/                    # PHPUnit tests, run against the booted API
└── AGENTS.md                 # Instructions for coding assistants

A request follows the folders in order: a route names the controller that handles it; the controller reads the request and calls a model; the model holds the business logic and returns DTOs; the controller returns them in Kipchak's response envelope:

{"code": 200, "status": "OK", "data": {"id": 4, "name": "Baybars", "reignFrom": 1260, "reignTo": 1277}}

Errors use the same envelope, from the Error middleware: throw one of Slim's HTTP exceptions, such as HttpNotFoundException, and the client receives {"code": 404, "status": "RESOURCE_NOT_FOUND", "data": "..."}.

OpenAPI

The OpenAPI document is generated from PHP attributes: operations on controller methods, schemas on DTOs, and the title and shared responses in api/OpenApi/Definition.php. /openapi.json serves it, and

composer openapi

writes it to openapi.yaml for client generation or CI. A problem found while generating the document, such as a reference to a schema that does not exist, is logged by /openapi.json, and printed by bin/openapi, which then exits with 1.

Tests

composer test

The tests boot the API as a worker does and send requests to it without a web server; see tests/ApiTestCase.php.

Drivers and middleware

Drivers connect the API to other services: databases, caches, queues, object storage, AI models and more. Install one with Composer, add its config file to config/ and initialise it in drivers/drivers.php. Middleware is added the same way in middlewares/middlewares.php, between its two Error::initialise($app) lines: the first turns an exception from a route into a JSON error response, and the last does the same for an exception from any middleware. Each package's page on kipchak.dev gives its installation, configuration and use.

The examples repository has a working route for every free driver and middleware, with a Docker Compose service for each one that needs a server.

Worker mode

FrankenPHP's worker mode boots the API once and keeps it in memory across requests, which makes it fast, but means anything stored in a static property or a global outlives the request. Keep request data in the request and in local variables. Caddy and FrankenPHP describes the worker loop in html/index.php and how to run without worker mode.

Licence

MIT. See LICENSE.