A lightweight MVC framework for PHP developers who want full control without the overhead of a full-stack behemoth.
// ── routes ──────────────────────────────────────── 1Router::get ('/posts', 'PostsController', 'index'); 2Router::get ('/posts/{id}', 'PostsController', 'show'); 3Router::post ('/posts', 'PostsController', 'store'); 4Router::delete('/posts/{id}', 'PostsController', 'destroy'); // ── controller ──────────────────────────────────── 5class PostsController extends Controller 6{ 7 protected array $rights = [ 8 'admin' => ['index', 'show', 'store', 'destroy'], 9 'user' => ['index', 'show'], 10 ]; 11 public function store(): void 12 { 13 $v = Validator::check(DataExchange::getValueAll(), [ 14 'PGtitle' => 'isNotEmpty|maxLength:200', 15 'PGcontent' => 'isNotEmpty', 16 ]); 17 if (!$v['status']) { $this->json($v['errors'], 422); } 18 $result = DBPosts::createPost(...); 19 $this->json(['id' => $result['data']], 201); 20 } 21}
A curated set of tools for building web applications and APIs — without pulling in half of the internet.
Matches URL + HTTP method. Dynamic params like {id} passed directly to controller methods. 404 and 405 handled automatically.
Declare $rights in each controller. The framework enforces authentication and role checks automatically on every request.
Raw SQL with named PDO bindings. Every method returns a predictable ['status','data','error'] array. All methods are static — no instantiation needed.
CSRF tokens, CSP nonce, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy, session fixation prevention — all enabled out of the box.
Write {{ $var }}, @foreach, @if, @include and @csrf. Templates compiled to cached PHP — no re-parsing on repeat visits.
Auto-detects Redis → APCu → File. No configuration needed — just call RateLimiter::tooManyAttempts().
DataExchange reads all GET/POST/JSON, runs CSRF verification, sanitizes, then clears superglobals. No accidental raw input access anywhere in your code.
MIME validated via finfo. Double-extension protection. Random filenames. One-call API — returns path, MIME, original name.
Pass total + current page → get back a complete data structure with page ranges, ellipsis markers, prev/next flags, and base URL.
Every request flows through a predictable, transparent pipeline. No magic. No hidden middleware stacks.
PSR-4 namespace mapping. System\Classes\* and App\Controllers\* loaded on demand — no scanning, no cache warming.
Logger, ErrorHandler, session hardening, security headers, rate limiter, and view engine all boot in index.php — in the right order.
URL matched against registered routes. HTTP method verified. Only then input is read and CSRF validated — no wasted work on 404s.
Controller __construct() calls allowAction() automatically. Checks session, resolves role, returns 401/403 if denied.
Controller method called with URL params. Read input via DataExchange, query DB via your module, return JSON or render a template.
JSON, HTML, XML, or redirect. Flash messages survive across redirects. All output is escape-by-default in templates.
No query builder to learn. Write the SQL you know — the framework handles PDO binding, fetch mode, and error normalization.
class DBOrders extends DataManager { public static function getOrdersPaged(int $page): array { return static::selectPaged( 'SELECT * FROM orders WHERE active = :a ORDER BY created_at DESC', [':a' => 1], $page, 20 ); } public static function createOrder(array $data): array { return static::transaction(function() use ($data) { static::insert('INSERT INTO orders ...', $data); static::update('UPDATE stock ...', [...]); }); } }
<!-- inherited globally: $user, $cspNonce, $flash --> @include('partials/header.tpl', ['title' => 'Orders']) @if($flash['success'] ?? false) <div class="alert">{{ $flash['success'][0] }}</div> @endif @foreach($orders as $order) <div> <strong>{{ $order['number'] }}</strong> <span>{{ $order['total'] }}</span> </div> @endforeach <form method="POST" action="/orders"> @csrf <input name="PGnumber"> <button>Create</button> </form> @include('partials/footer.tpl')
Familiar directives, zero PHP dependency on the full Blade stack. Templates compile once and cache — reopening the file on next request only if the source changed.
{{ $var }} and raw {!! $html !!}@csrf inserts hidden token field automaticallySecurity features are not optional add-ons. They are baked into the request pipeline and active on every response.
No Composer required. No vendor directory to commit. No dependency vulnerabilities to audit.
Clone the repo, configure your database, and you're live in minutes.