Installation
Glueful has two entry points:
glueful/api-skeletonfor most users. This is the recommended path.glueful/frameworkif you are embedding the framework into an existing project.
Requirements
- PHP 8.3+
- Composer 2+
- One of SQLite (default), MySQL, or PostgreSQL
Recommended: API Skeleton
Create a new project from the starter app:
composer create-project glueful/api-skeleton my-api
cd my-api
The skeleton already includes:
- a CLI entrypoint at
glueful - framework bootstrap in
bootstrap/app.php - example routes in
routes/api.php - example controller in
app/Controllers/WelcomeController.php, registered inapp/Providers/AppServiceProvider.php - default SQLite storage in
storage/database/glueful.sqlite - three official extensions installed and enabled in
config/extensions.php:glueful/users(the user store that makes login work),glueful/email-notification(the email channel for verification / password-reset mail), andglueful/media(image processing and thumbnails)
Run it
composer create-project already installs dependencies, copies .env, creates the SQLite database, and runs php glueful install --force --quiet for you (generating keys and running migrations, including the enabled extensions' tables) — so the app is ready. Start the dev server:
php glueful serve # http://localhost:8000
php glueful serve --port=8080 --watch
Then verify the starter routes:
curl http://localhost:8000/welcome
curl http://localhost:8000/v1/status
curl http://localhost:8000/health
Using MySQL or PostgreSQL
php glueful install is engine-agnostic. Run it interactively to pick mysql, pgsql, or sqlite and enter credentials — it tests the connection first (a failed test leaves .env untouched), writes .env, and migrates:
php glueful install
Pass --quiet to reuse the existing .env without prompts (CI, scripts), or --skip-database to skip database setup entirely.
URL prefixes
Your route files are not prefixed automatically — the skeleton's routes/api.php adds its own v1 group, which is why the starter route is /v1/status. Framework and extension API routes (auth, blobs, /me, …) are mounted under the configured API prefix, /api/v1 by default:
curl -X POST http://localhost:8000/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"[email protected]","password":"secret"}'
The prefix is controlled by API_USE_PREFIX, API_PREFIX, and API_VERSION_IN_PATH in .env; see Routing.
Add your first route
Open routes/api.php and add a route inside the existing v1 group:
<?php
use Glueful\Routing\Router;
use Glueful\Http\Response;
use App\Controllers\WelcomeController;
$router->group(['prefix' => 'v1'], function (Router $router) {
$router->get('/status', [WelcomeController::class, 'status']);
$router->get('/hello', function () {
return Response::success([
'message' => 'Hello from Glueful',
'timestamp' => date('c'),
]);
});
});
$router->get('/welcome', [WelcomeController::class, 'index']);
Test it:
curl http://localhost:8000/v1/hello
Any other routes/*.php file you create is loaded automatically too (files starting with _ are skipped, so you can keep shared partials there).
Generate new code
Glueful's current generators use the scaffold:* namespace:
php glueful scaffold:controller UserController
php glueful scaffold:model User
php glueful scaffold:dto CreateUserData
Scaffolding creates the class only. Add a route for a new controller, and register the controller in AppServiceProvider::services() (as the skeleton does for WelcomeController) so the router can resolve it — see Controllers.
Alternative: Framework Only
Install the framework package into an existing PHP project:
composer require glueful/framework
Create a minimal bootstrap:
<?php
declare(strict_types=1);
use Glueful\Framework;
use Symfony\Component\HttpFoundation\Request;
require __DIR__ . '/vendor/autoload.php';
$framework = Framework::create(__DIR__)
->withConfigDir(__DIR__ . '/config')
->withEnvironment($_ENV['APP_ENV'] ?? 'development');
$app = $framework->boot();
$request = Request::createFromGlobals();
$response = $app->handle($request);
$response->send();
$app->terminate($request, $response);
Use this path only if you already know the project structure you want. If not, use the API skeleton.