PHP 8.1+ · No dependencies · Production ready

Build fast.
Ship confident.

A lightweight MVC framework for PHP developers who want full control without the overhead of a full-stack behemoth.

app/routes/api.php  +  app/controllers/PostsController.php
// ── 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}
            
14
Core classes
0
External dependencies
PHP 8.1
Minimum version
PSR-4
Custom autoloader
3-tier
Rate limiter fallback

Everything you need.
Nothing you don't.

A curated set of tools for building web applications and APIs — without pulling in half of the internet.

🔀

Smart Router

Matches URL + HTTP method. Dynamic params like {id} passed directly to controller methods. 404 and 405 handled automatically.

🔐

Role-based Auth

Declare $rights in each controller. The framework enforces authentication and role checks automatically on every request.

🗄️

DataManager ORM-free

Raw SQL with named PDO bindings. Every method returns a predictable ['status','data','error'] array. All methods are static — no instantiation needed.

🛡️

Security by default

CSRF tokens, CSP nonce, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy, session fixation prevention — all enabled out of the box.

Blade-lite Templates

Write {{ $var }}, @foreach, @if, @include and @csrf. Templates compiled to cached PHP — no re-parsing on repeat visits.

🚦

Rate Limiter

Auto-detects Redis → APCu → File. No configuration needed — just call RateLimiter::tooManyAttempts().

📥

Input Isolation

DataExchange reads all GET/POST/JSON, runs CSRF verification, sanitizes, then clears superglobals. No accidental raw input access anywhere in your code.

📤

File Upload

MIME validated via finfo. Double-extension protection. Random filenames. One-call API — returns path, MIME, original name.

📄

Pagination helper

Pass total + current page → get back a complete data structure with page ranges, ellipsis markers, prev/next flags, and base URL.

Request lifecycle

Every request flows through a predictable, transparent pipeline. No magic. No hidden middleware stacks.

Step 01

Autoloader

PSR-4 namespace mapping. System\Classes\* and App\Controllers\* loaded on demand — no scanning, no cache warming.

Step 02

Bootstrap

Logger, ErrorHandler, session hardening, security headers, rate limiter, and view engine all boot in index.php — in the right order.

Step 03

Routing

URL matched against registered routes. HTTP method verified. Only then input is read and CSRF validated — no wasted work on 404s.

Step 04

Auth check

Controller __construct() calls allowAction() automatically. Checks session, resolves role, returns 401/403 if denied.

Step 05

Your method

Controller method called with URL params. Read input via DataExchange, query DB via your module, return JSON or render a template.

Step 06

Response

JSON, HTML, XML, or redirect. Flash messages survive across redirects. All output is escape-by-default in templates.

Raw SQL.
Clean API.

No query builder to learn. Write the SQL you know — the framework handles PDO binding, fetch mode, and error normalization.

  • Named parameters with auto type detection
  • Transactions with automatic rollback on exception
  • Batch insert and upsert helpers
  • Paginated queries with total row count built in
  • Static methods — call directly on your DB class, no instantiation
app/models/db.orders.php
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 ...', [...]);
    });
  }
}
app/views/orders/index.tpl
<!-- 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')

Blade-lite.
No Blade overhead.

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.

  • Auto-escaped {{ $var }} and raw {!! $html !!}
  • @csrf inserts hidden token field automatically
  • @if · @foreach · @for · @include
  • CSP nonce shared globally — add to every script/style
  • Path traversal protected via realpath validation

Secure by default.
Not by configuration.

Security features are not optional add-ons. They are baked into the request pipeline and active on every response.

🔑 CSRF token verification
🧱 Content Security Policy
🔒 HSTS enforcement
🚫 X-Frame-Options: DENY
👻 No-referrer policy
📵 Permissions-Policy
🍪 HttpOnly · Secure · SameSite
🔄 Session fixation prevention
⏱️ Rate limiting (Redis/APCu/File)
💉 PDO named param binding
📂 MIME validation via finfo
🧹 Superglobal isolation

Built with nothing
but PHP and intent.

No Composer required. No vendor directory to commit. No dependency vulnerabilities to audit.

PHP 8.1+
MySQL / PDO
Redis (optional)
APCu (optional)
PSR-4 Autoloader
Blade-lite Templates
Custom MVC Core

Ready to build?

Clone the repo, configure your database, and you're live in minutes.

Read the documentation See a full example