sahilphp / starter-kit
A starter application for building projects with the SahilPHP framework.
Requires
- php: ^8.4
- sahilphp/framework: ^1.0
Requires (Dev)
- phpunit/phpunit: ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A ready-to-run application for the SahilPHP framework: routing, views,
sessions, authentication, database, queue, mail, and a Tailwind CSS frontend
(or Bootstrap 5, selected when generating a project) — all wired and testable
from the first composer install.
The framework itself is the reusable sahilphp/framework package. This
repository owns the application: configuration, providers, routes, views,
entry points and tests.
Requirements
Server requirements
PHP 8.4+ is required to run this application. Most shared hosts offer PHP 8.4 or newer. If your host is running an older PHP version, you will need to upgrade or switch to a different hosting provider.
Required extensions:
- ext-mbstring
- ext-json
- ext-openssl
- ext-pdo (MySQL/PostgreSQL database)
- ext-ctype
- ext-tokenizer
- ext-fileinfo
Optional extensions:
- ext-gd (image manipulation)
- ext-xmlreader
- ext-xmlwriter
Optional: A writable storage/ directory (it ships with .gitkeep files)
Optional: MySQL or PostgreSQL for database-backed features
The application boots with sensible defaults when no .env file is present:
APP_ENV=developmentAPP_DEBUG=falseAPP_TIMEZONE=UTC
For production deployment, set APP_ENV=production and APP_DEBUG=false.
See the PHP documentation for installation instructions.
- PHP 8.4+ (this kit's
composer.jsonrequires^8.4) - Composer 2.x
- Node.js 20.19+ or 22.12+ with npm — only for the optional frontend
asset commands (
npm run dev,bin/sahil ui:build). The PHP application boots without Node. - A writable
storage/directory (it ships with.gitkeepfiles) - Optional: MySQL or PostgreSQL for database-backed features
Installation
composer create-project sahilphp/starter-kit my-app
cd my-app
create-project copies the application, installs sahilphp/framework and its
dependencies, then runs three hooks:
.env.exampleis copied to.env(skipped when.envalready exists);php bin/sahil key:generatewrites a uniqueAPP_KEY;php bin/sahil storage:preparecreates the writable storage tree.
No .env file is strictly required: the application boots with the
documented defaults (APP_ENV=development, APP_DEBUG=false, UTC). Copy the
template yourself when you need database, mail, session or asset overrides:
cp .env.example .env
php bin/sahil key:generate # writes APP_KEY; --force replaces an existing key
Creating a project with the installer
The starter-kit also contains a guided installer, so a checkout can create another application without publishing anything first:
php bin/sahil new my-app
The installer asks for the project name and then for exactly one UI framework:
Choose your UI framework:
[1] Tailwind CSS
[2] Bootstrap 5
It copies the application sources, removes frontend files that do not belong to
the selected profile, installs PHP and frontend dependencies, and generates
.env with a fresh APP_KEY. vendor/, node_modules/, build output,
sessions and machine-local files are never copied from the source checkout.
Non-interactive use is supported for automation and CI. A UI choice is mandatory in that mode; the installer never falls back to installing both:
php bin/sahil new my-app --ui=tailwind --no-interaction php bin/sahil new my-app --path=/tmp/my-app --ui=bootstrap --no-interaction php bin/sahil new my-app --ui=tailwind --no-install --no-interaction
| Option | Meaning |
|---|---|
name |
Project name (letters, digits, dots, underscores and hyphens) |
--path=DIR |
Exact destination directory (default: ./<name>) |
--ui=NAME |
tailwind or bootstrap; required when non-interactive |
--profile=NAME |
Alias for --ui |
--no-interaction, -n |
Never prompt; requires a name and --ui |
--interactive |
Force prompts even when STDIN is not a TTY |
--no-install |
Generate files without running Composer or npm |
--no-dev |
Run Composer without development dependencies |
The installer refuses non-empty destination directories and never overwrites an existing project. After creation, the printed next steps show how to review the application, build the selected assets and start the server.
Working on the framework locally
To develop against an unreleased framework, clone it next to this repository and point Composer at that checkout (remove the entry before committing):
composer config repositories.framework \
'{"type":"path","url":"../framework","options":{"symlink":true,"versions":{"sahilphp/framework":"1.0.0"}}}'
composer update sahilphp/framework
First run
Verify the application boots (no database required):
php bin/sahil about php bin/sahil --version php bin/sahil env:check # lists known variables; never prints values php bin/sahil key:generate # only needed when .env has no APP_KEY yet php bin/sahil storage:prepare # create any missing storage directories
Start the development server from the project root:
php sahil start # http://127.0.0.1:8000 php sahil start --port=8088 # a different port php sahil start --host=0.0.0.0 --port=8088 composer start -- --port=8088 # the same command through Composer
php sahil <command> runs every CLI command without the bin/ prefix;
php bin/sahil start is the identical command. When the port is already taken,
start moves to the next free port and prints both, so composer start never
fails with a raw "Address already in use" error.
start runs php -S 127.0.0.1:8000 -t public public/index.php for you:
-t public sets the document root so static assets under public/ are served.
Then check it:
curl -s http://127.0.0.1:8000/health # {"status":"ok","framework":"SahilPHP","environment":"development","booted":true,...} curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8000/no-such-page # 404
Open http://127.0.0.1:8000/ for the sample home page and http://127.0.0.1:8000/ui-kit for the component gallery.
Press Ctrl+C to stop the server.
Frontend assets
The recorded UI profile of this checkout is tailwind (Tailwind CSS v4),
stored in .sahil-ui.json. Projects created with bin/sahil new --ui=bootstrap
record bootstrap instead; a generated application always has exactly one
framework, never both. Asset URLs are generated by the active profile, so the
same templates work in development and production.
Development — start Vite next to the PHP server (two terminals):
npm ci
npm run dev # or: php bin/sahil ui:dev
In development the layouts read public/hot, the file ui:dev writes with the
Vite server it actually started. Vite starts on http://127.0.0.1:5173 and
moves to the next free port when that one is busy — the pages follow, no
restart or config edit needed. Without Vite running, the pages still render but
are unstyled.
Production — build deterministic files into public/build/assets/:
npm ci php bin/sahil ui:build --clean APP_ENV=production php -S 127.0.0.1:8000 -t public public/index.php
Build output is gitignored, so a fresh checkout must run the build before
serving with APP_ENV=production; otherwise / and /ui-kit return a safe
500 because the expected asset files are missing.
Check the frontend state at any time:
php bin/sahil ui:status # add --json for machine-readable output
Install a different profile (tailwind, bootstrap, both, none) with
php bin/sahil ui:install <profile>; add --dry-run to preview, --merge or
--overwrite to resolve existing files.
Branding
The official SahilPHP logo ships in every project and every layout already links it:
| File | Purpose |
|---|---|
public/favicon.ico |
browser tab icon |
public/logo.png |
official lockup (mark + wordmark) for navigation and heroes |
public/logo-mark.png |
mark only, for footers and compact surfaces |
public/apple-touch-icon.png |
iOS home-screen icon |
Templates render the logo through partials/brand, so replacing those files
updates the welcome page, navigation, auth pages and dashboard at once.
APP_NAME changes the application name in titles and copy; the logo remains
the framework mark.
Authentication pages
Generate login, register, forgot-password, reset-password and dashboard pages for the installed UI profile:
php sahil make:auth # pages for the recorded profile php sahil make:auth --ui=bootstrap # choose a profile explicitly php sahil make:auth --dry-run # print the plan, write nothing php sahil make:auth --force # replace existing pages (backup kept)
Tailwind projects get shadcn/ui-style pages and a sidebar dashboard; Bootstrap
projects get a Bootstrap 5 design. The command writes
app/Http/AuthController.php, routes/auth.php and the templates under
resources/views/:
| Route | Template |
|---|---|
/login |
auth/login.sahil.php |
/register |
auth/register.sahil.php |
/forgot-password |
auth/forgot-password.sahil.php |
/reset-password/{token} |
auth/reset-password.sahil.php |
/dashboard |
pages/dashboard.sahil.php |
WebRoutesProvider loads routes/auth.php automatically when it exists, so
the pages work as soon as the command finishes. The handlers render pages
only: they do not authenticate, create accounts or send mail. Wire
AuthManager and PasswordReset into the POST handlers in routes/auth.php
when you add real users. Existing pages are never overwritten without
--force, which backs them up under storage/framework/auth-backups/.
CLI
bin/sahil boots the application from bootstrap/app.php (UI commands run
before boot, so they work in a partially configured project).
php bin/sahil --help php bin/sahil about # app name, environment, debug, PHP, booted php bin/sahil config:show database # secrets are always [redacted] php bin/sahil env:check # variable names only, never values php bin/sahil ui:install|ui:dev|ui:build|ui:status|ui:theme php bin/sahil make:auth [--ui=tailwind|bootstrap] [--force] [--dry-run] php bin/sahil migrate|migrate:status|migrate:rollback|db:seed php bin/sahil queue:work|queue:failed|queue:retry|queue:flush php bin/sahil schedule:list|schedule:run
Destructive operations (migrate:rollback, db:seed, schema changes in
production) require --force. The CLI prints one clear error line instead of
a stack trace.
Configuration
config/*.phpare plain arrays keyed by file name; read them withconfig()->get('app.name'). SetAPP_NAMEto change the display name used in page titles and navigation; the framework identity remains SahilPHP.bootstrap/app.phproots the application at the project directory, loads.envwhen present, loadsconfig/, registersbootstrap/providers.php, and boots the service providers.sahil_bootstrap()returns the same application instance for the lifetime of a process.- Environment variables are listed by
php bin/sahil env:checkand defaulted inconfig/. Put local values in.env(gitignored) or inject them from the environment in production.
Database (optional)
Boot, routing, views and /health work without a database. For
database-backed features, set DB_* in .env (see config/database.php),
then apply the shipped migrations:
php bin/sahil migrate:status php bin/sahil migrate
The queue and scheduler tables are part of those migrations.
Security
Production checklist:
APP_KEY— generated byphp bin/sahil key:generate, required before usingSahil\Encryption\Encrypter(AES-256-GCM + HMAC). Keep it secret and unique per installation.APP_ENV=productionandAPP_DEBUG=false— debug output and verbose errors are never shown to clients unless debugging is explicitly enabled.- Web root is
public/— copydocs/deploy/nginx.conf.exampleordocs/deploy/apache-vhost.conf.example;public/.htaccesshandles Apache rewrites..env,config/,storage/andvendor/must never be reachable over HTTP. - Secure headers —
SecurityHeadersruns for every response (nosniff,X-Frame-Options: DENY,Referrer-Policy,Permissions-Policy,Cross-Origin-Opener-Policy). Add a CSP through the middleware overrides once your asset policy is settled. - HTTPS + secure cookies — set
SESSION_SECURE=truebehind TLS. - Queue payloads — set
queue.allowed_jobsinconfig/queue.phpto the job classes you actually dispatch; payloads may then instantiate nothing else. - Dependencies —
composer auditruns in CI; keep packages current.
Report vulnerabilities privately — see SECURITY.md. A static
public/500.html is served by the web server when PHP itself fails.
Tests
composer test
This runs the application test suite (bootstrap, console/CLI, UI commands and
sample-view rendering). Database integration tests in the framework package
are skipped unless SAHIL_DB_TEST_MYSQL / SAHIL_DB_TEST_PGSQL are set.
Project layout
| Path | Purpose |
|---|---|
app/Http/ |
Controllers (App\Http) |
app/Providers/ |
Service providers registered at boot |
bin/sahil |
CLI entry point |
bootstrap/app.php |
Application bootstrap (sahil_bootstrap()) |
bootstrap/providers.php |
Provider manifest |
config/ |
Configuration arrays |
database/ |
Migrations and seeders |
public/index.php |
HTTP front controller |
public/css, public/js |
Hand-written UI kit assets |
resources/ |
Frontend sources for the Vite build |
routes/web.php |
Route table (/, /ui-kit, /health) |
routes/auth.php |
Auth pages generated by make:auth (optional) |
auth-stubs/ |
Templates and controller source for make:auth |
public/logo.png, public/logo-mark.png |
Official SahilPHP logo assets |
storage/ |
Logs, compiled views, sessions, cache, uploads |
tests/ |
Application test suite (Tests\) |
views/ |
Layouts, pages, partials and profile examples |
.sahil-ui.json |
Recorded UI profile (tailwind in this checkout) |
Troubleshooting
| Symptom | Cause and fix |
|---|---|
The url supplied for the path (../framework) repository does not exist |
Clone the framework repository next to this one (see Installation). |
| CSS/JS links return 404 | Use php sahil start (or composer start -- --port=8088); starting only the router script leaves static assets unreachable. |
/ and /ui-kit return 500 {"error":"server_error"} with APP_ENV=production |
Build the assets: php bin/sahil ui:build --clean (they are gitignored). |
| Pages render unstyled in development | Start Vite (npm run dev or sahil ui:dev); the layouts point at http://127.0.0.1:5173. |
ui:status reports missing sources or packages |
Run php bin/sahil ui:install (and npm ci if packages are missing). |
Contributing
Development setup, the quality gates and the local-framework workflow are in CONTRIBUTING.md; release history is in CHANGELOG.md; community expectations are in CODE_OF_CONDUCT.md.
License
Released under the MIT License. See LICENSE for the full text.