n0nag0n / slim-ai-skeleton
AI-friendly Slim 4 skeleton
Requires
- php: ^8.2
- doctrine/dbal: ^4.2
- php-di/slim-bridge: ^3.4
- slim/psr7: ^1.8
- slim/slim: ^4.15
- slim/twig-view: ^3.4
- tracy/tracy: ^2.10
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpstan/phpstan-doctrine: ^2.0
- phpunit/phpunit: ^11.0
- slevomat/coding-standard: *
- squizlabs/php_codesniffer: ^4.0
This package is auto-updated.
Last update: 2026-05-17 15:16:59 UTC
README
A starter project for building PHP web apps with the Slim 4 framework. It's designed to work well with AI coding tools (Cursor, Claude Code, Windsurf, etc.) — the code is simple, explicit, and easy for both humans and AIs to understand.
What you get
A working web app out of the box — it serves a homepage, a health-check endpoint, and has a database ready to go. Everything is set up so you can start adding your own pages and features immediately.
Features
- Slim 4 — a lightweight PHP framework for handling web requests and responses
- PHP-DI — automatic dependency injection container
- Doctrine DBAL — database query layer with parameterized queries
- Twig — a template system for building HTML pages separate from your PHP code
- Session handling —
App\Util\Sessionwraps PHP's native sessions and is injectable via constructor - Flash messages — one-request survival messages for form submission feedback via
App\Util\Flash - Validation — method-chaining input validation with
App\Util\Validator(required, email, length, matches, etc.) - Pagination — offset/limit calculator with
App\Util\Paginationfor list endpoints - CLI console —
php consolewith commands to scaffold controllers, models, migrations, and more - Tracy — a debug bar with panels for requests, responses, routes, sessions, and database queries
- PHPUnit — testing framework to make sure your code works
- PHPStan — static analysis to catch bugs before runtime
- PHP_CodeSniffer — enforces consistent code style
- SQLite by default — file-based database, no need for MySQL or PostgreSQL
How AI fits in
AI coding tools work best when code is predictable and easy to trace. This project follows patterns that AIs recognize:
- All routes in one file (
config/routes.php) — the AI always knows where to add a new URL - No magic — every import is explicit, no auto-discovery, no hidden configuration
- One file per concept — controllers handle HTTP, models handle data, templates handle HTML
If you're using an AI coding assistant, just open this project in your editor and the AI will
already understand the patterns. The file AGENTS.md contains detailed instructions for AI tools.
Requirements
- PHP 8.2 or higher
- Composer
- SQLite extension (
pdo_sqlite) — usually included with PHP by default
Quick Start
composer create-project n0nag0n/slim-ai-skeleton my-project
cd my-project
composer migrate
composer start
Open http://localhost:8080 in your browser. You should see the homepage.
Commands
| Command | Description |
|---|---|
composer start |
Start the development server on port 8080 |
composer test |
Run all tests |
composer lint |
Check code style with PHP_CodeSniffer |
composer stan |
Run PHPStan static analysis |
composer cs-fix |
Auto-fix code style issues |
composer migrate |
Run pending database migrations |
php console |
List all CLI commands (scaffolding, cache, routes) |
composer sync-ai-instructions |
Sync AGENTS.md to AI tool config files |
Your first new page
Here's how to add a new page at /hello:
-
Add a route in
config/routes.php:$app->get('/hello', [App\Controller\HelloController::class, 'index']);
-
Create a controller at
src/Controller/HelloController.php:<?php namespace App\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Views\Twig; class HelloController { public function __construct(private Twig $twig) {} public function index(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { return $this->twig->render($response, 'hello.twig'); } }
-
Create a template at
templates/hello.twig:{% extends 'layout.twig' %} {% block content %} <h1>Hello, world!</h1> {% endblock %} -
Restart the server and visit
http://localhost:8080/hello.
Project Structure
├── config/
│ ├── console.php # CLI command definitions
│ ├── dependencies.php # Service definitions for the DI container
│ ├── middleware.php # Middleware stack (runs on every request)
│ └── routes.php # ALL routes in one file — add new pages here
├── migrations/ # Database migration files (SQL)
├── public/
│ └── index.php # Entry point — every request goes through here
├── src/
│ ├── Console/ # CLI commands (scaffolding, cache, routes)
│ ├── Controller/ # Request handlers — one file per page or feature
│ ├── Debug/ # Tracy debug panels and query logging
│ ├── Model/ # Database query code
│ ├── Renderer/ # Response helpers (e.g., JSON)
│ └── Util/ # Utility classes — Sessions, Flash, Validation, Pagination
├── templates/ # Twig HTML templates
│ └── error/ # Error pages (404, 500)
└── tests/ # PHPUnit tests
├── bootstrap.php
├── TestCase.php # Base test your tests extend from
├── Controller/
├── Model/
├── Renderer/
└── Util/
Environment Variables
| Variable | Default | What it does |
|---|---|---|
APP_ENV |
dev |
Set to production when deploying |
DEBUG_MODE |
true |
Shows the Tracy debug bar. Turn off in production. |
DB_DRIVER |
pdo_sqlite |
Database driver (pdo_mysql, pdo_pgsql, etc.) |
DB_PATH |
var/database.sqlite |
Where the SQLite database file lives |
Error Handling
- Development (
DEBUG_MODE=true): Tracy shows a detailed error page with stack traces. - Production (
DEBUG_MODE=false): Shows a friendly error page (HTML for browsers, JSON for API calls).
Troubleshooting
Port 8080 is already in use
composer start
# Error: Address already in use
Use a different port: php -S localhost:8081 -t public
php migrate fails
Make sure the var/ directory is writable. SQLite creates the database file there.
Nothing shows up at localhost:8080
The server needs to keep running in your terminal. Open a second terminal or use the -t flag
to run it in the background: php -S localhost:8080 -t public > /dev/null 2>&1 &
What's next?
- Try adding your own page using the walkthrough above
- Run
composer testto confirm everything still works after your changes - Ask your AI assistant: "Add a page that shows the current time"
- When you're ready to deploy, set
DEBUG_MODE=falseandAPP_ENV=productionin.env
License
MIT