A project starter built on Maestro, a self-written lightweight PHP 8.2 MVC framework, with a Svelte 5 frontend. PHP handles the JSON API and authentication; Svelte handles all UI rendering.
admin / owner)PHP backend (Maestro MVC) → JSON API at /api/*
Svelte 5 frontend → SPA served from public/build/
In development: Vite dev server runs on :5173 and proxies /api/* to PHP on :8888. Hot module replacement works out of the box.
In production: npm run build compiles Svelte to public/build/. PHP serves those static files and handles all /api/* requests. No Node.js needed on the server.
Built on Maestro, a self-written PHP 8.2 MVC framework using:
| Namespace | Directory | Role |
|---|---|---|
Framework\ |
src/ |
Core framework (Router, Kernel, Database, …) |
App\ |
app/ |
Application code (Controllers, Models, Repositories) |
| File | Role |
|---|---|
frontend/src/App.svelte |
Root component — bootstraps auth, client-side router |
frontend/src/lib/router.svelte.js |
router.path state + navigate() (History API) |
frontend/src/lib/auth.svelte.js |
Global auth.user state |
frontend/src/lib/api.js |
apiFetch / post wrappers (JSON + session cookies) |
frontend/src/components/Layout.svelte |
Nav, footer shell |
frontend/src/pages/ |
One file per route |
pdo_sqlite extension# 1. Install PHP dependencies
composer install
# 2. Install frontend dependencies
cd frontend && npm install && cd ..
# 3. Run migrations (creates database/maestro.sqlite + default admin account)
php maestro migrate
# 4. Start PHP API + Vite dev server together
php maestro dev
Open http://localhost:5173.
A default admin account is created on first migrate:
admin@localhost |
|
| Password | admin |
Change the password after first login at /profile.
| Command | Description |
|---|---|
php maestro dev |
PHP API on :8888 + Vite dev server on :5173 |
php maestro serve |
PHP server only on :8888 (no Vite) |
php maestro build |
Compile Svelte → public/build/ for production |
php maestro migrate |
Run all SQL migrations |
php maestro phpcs |
Check PHP code style (PSR via phpcs) |
php maestro phpstan |
Run static analysis (level 8) |
php maestro deptrac |
Check architecture layer rules |
SQLite — the database file lives at database/maestro.sqlite and is created automatically by php maestro migrate. To use a different path, export APP_DB_DSN before running:
export APP_DB_DSN="sqlite:/absolute/path/to/your.sqlite"
php maestro serve
app/
Controllers/
Api/ JSON API controllers (consumed by Svelte)
AuthController me, login, logout, invite flow, profile
UserController Admin user management
AuthController Legacy Twig controllers (kept for reference)
HomeController
UserController
Models/ Plain data objects (User, Role)
Repositories/ Data-access layer (UserRepository + interface)
views/ Twig error templates (403, 404, 500)
src/
Kernel.php Bootstrap: wires container, database, router
Router.php Regex-based routing
Database.php PDO wrapper
ResponseFactory.php Twig views + JSON responses
ServiceContainer.php Simple DI container
frontend/
src/
App.svelte Root component + router
lib/ Shared state and API helpers
components/ Layout, ErrorAlert
pages/ Home, Login, Invite, Profile, AdminUsers, NotFound
index.html Vite entry point
vite.config.js Build config (output → public/build/, proxy /api/)
database/
0_reset.sql Drop all tables
1_create_tables.sql Schema (role, user)
6_auth_setup.sql Seed roles
public/
index.php Single entry point — serves Svelte SPA or routes /api/*
.htaccess URL rewriting (Apache)
build/ Compiled Svelte output (git-ignored, generated by npm run build)
maestro CLI tool
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/auth/me |
— | Current user or 401 |
| POST | /api/auth/login |
— | Authenticate |
| POST | /api/auth/logout |
— | Sign out |
| GET | /api/auth/invite/{token} |
— | Validate invite token |
| POST | /api/auth/invite/{token} |
— | Set password + activate |
| GET | /api/auth/profile |
✓ | Get current user |
| POST | /api/auth/profile |
✓ | Update name / email / password |
| GET | /api/users |
admin | List users + roles |
| POST | /api/users |
admin | Create user + generate invite |
| POST | /api/users/{id} |
admin | Update user |
| POST | /api/users/{id}/invite |
admin | Regenerate invite link |
pdo_sqlite extensionmod_rewrite (or Nginx equivalent)Run this locally (or in CI) before deploying:
php maestro build
This writes compiled assets to public/build/. Commit or upload this directory to the server.
composer install --no-dev --optimize-autoloader
Only public/ is the web root — everything else must live above it.
| Upload | To |
|---|---|
app/ |
above document root |
src/ |
above document root |
vendor/ |
above document root |
database/ |
above document root |
public/index.php |
document root (public_html/ or equivalent) |
public/.htaccess |
document root |
public/build/ |
document root |
A typical shared-host layout:
~/
app/
src/
vendor/
database/ ← maestro.sqlite lives here
public_html/ ← document root
index.php
.htaccess
build/
With SSH access:
php maestro migrate
Without SSH (phpMyAdmin or similar): run the files in database/ manually in alphabetical order.
Log in with admin@localhost / admin and update your password at /profile immediately.
This project includes a CLAUDE.md with architecture notes for Claude Code, and a .claude/settings.json that configures a hook to automatically run phpcs after every PHP file edit.