Search by

lekoala / kaly

lekoala

A small modular PSR HTTP framework with convention-based routing and first-class dependency injection

Package info

github.com/lekoala/kaly

pkg:composer/lekoala/kaly

Statistics

Installs: 44

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

0.4.0 2026-10-15 22:38 UTC

This package is auto-updated.

Last update: 2026-10-16 14:46:57 UTC


README

Kaly

Kaly PHP framework

Latest Version Total Downloads License PHP Version Require

A small modular PSR HTTP framework with convention-based routing and first-class dependency injection

Kaly is an opinionated but lightweight application framework built on PHP standards:

  • PSR based: PSR-7 messages, PSR-11 container, PSR-15 middleware.
  • Dependency injection: powered by kaly-di, autowiring and explicit definitions.
  • Hierarchical routing: every url belongs to one module, which resolves it with conventions (controllers map to URIs), its own route table or a custom resolver — all declared in its config.php.
  • Modular architecture: each module has its own config, controllers, templates and assets.
  • Middleware support: plain PSR-15 middleware, applied in bands (incoming, routed, outgoing).
  • Multilingual support: built-in locale detection.
  • Renderer agnostic: Latte (recommended), kaly-tpl (lightweight native PHP) or Twig, through tiny adapters.
  • No database, no ORM, no forms: Kaly stays a small HTTP framework.
  • Auth and browser security bundled: request identity with permissions, session login, CSRF, CSP nonces and method override (see docs/auth.md and docs/security.md).
  • Rate limiting: compose a PSR-15 middleware with a shared limiter; Symfony RateLimiter is recommended (see the rate limiting recipe).
  • No HTTP client bundled: outgoing calls go through any PSR-18 client, such as Buzz or Symfony HttpClient (see the HTTP client recipe).

Stability

Kaly is 0.x: breaking changes are made deliberately, in favor of a smaller and sharper public API rather than piled up behind aliases and deprecation layers. Read UPGRADE.md before upgrading: it lists every removal and rename, with the migration.

Internal lekoala/kaly-di and lekoala/kaly-tpl are 0.x too and may evolve independently.

UPGRADE.md is the record of what changed and why. There is no promise of backward compatibility within 0.x.

Views

Kaly ships no template engine: return a Kaly\View\View from a controller and register a Kaly\View\RendererInterface (see docs/views.md). Optional adapters are provided for Latte, kaly-tpl and Twig.

Requirements

  • PHP 8.3+
  • A PSR-7 implementation for your application (Nyholm is recommended); the core only depends on the PSR interfaces.

Installation

composer require lekoala/kaly nyholm/psr7

Agent skill for applications

Kaly ships the kaly skill and its five references in vendor/lekoala/kaly/skills/kaly/. It guides agents working on applications that consume Kaly. The bundle is included in Composer packages; installation does not change the application's agent configuration.

For Codex, copy the entire folder into the application's .agents/skills/ directory, a supported local skill location. Run from the application root on macOS/Linux:

mkdir -p .agents/skills
cp -R vendor/lekoala/kaly/skills/kaly .agents/skills/

Or in PowerShell:

New-Item -ItemType Directory -Force .agents/skills | Out-Null
Copy-Item -Recurse vendor/lekoala/kaly/skills/kaly .agents/skills/

Invoke it explicitly with $kaly, or let Codex select it for relevant tasks. For other agents, expose the same folder using their skill installation mechanism. Refresh the copied bundle after upgrading Kaly, including its references/ folder.

Quick start

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

Kaly\Core\App::create(dirname(__DIR__))->run();
// modules/app/config.php  ->  the module exists because of this file,
//                             and it owns the root because it mounts '/'
use Kaly\Core\Module;

return static function (Module $module): void {
    $module->mount('/');
};
// modules/app/src/Controller/IndexController.php  ->  GET /
namespace App\Controller;

final class IndexController
{
    public function index(): string
    {
        return 'Hello';
    }
}

A module is any folder of modules/ with a config.php (it may be empty): without it the folder is invisible and its urls 404. Any other module is routable under its name (modules/Shop answers on /shop/...). See UPGRADE.md when updating.

Documentation

  • Online: https://lekoala.github.io/kaly/
  • Raw Markdown in docs/ stays readable directly on GitHub
  • Local preview: composer docs (requires Ruby + Bundler, serves the Jekyll site with live reload)

Testing

composer test