actra / yuf-skeleton
A minimal "Hello World" application to start a new project with the yuf framework.
Requires
- php: >=8.5
- actra/yuf: ^8.4.0
Requires (Dev)
- actra/coding-standard: ^1.34.0
- phpunit/phpunit: ^13.4.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A minimal "Hello World" application to start a new project with the yuf framework.
Create a project
With DDEV (needs only DDEV and Git, no local PHP or Composer):
bash <(curl -fsSL https://raw.githubusercontent.com/Actra-AG/yuf-skeleton/main/setup.sh)
It asks for the project name, the copyright holder and the license (default: MIT), creates the project in a new
directory, fills in the file header and allowedDomains (<name>.ddev.site), makes the first Git commit and opens the
Hello World page. Run all further composer commands as
ddev composer.
Without DDEV: run composer create-project actra/yuf-skeleton my-project with PHP 8.5 and the extensions required
by yuf. Use a web server with public/ as the document root, HTTPS (yuf redirects HTTP to HTTPS), and all requests for
non-existent files sent to public/index.php (see public/.htaccess for Apache). Add your host name to
allowedDomains in .env.php.
After creating the project:
- Set
'debug' => truein.env.phpon your development machine: the error pages then show the details of the exception..env.example.phpshipsfalse, the value for production. - Without
setup.sh: replace the placeholders[Your company or name]and[License of your project]in the file header (copyright:andlicense:in.php-cs-fixer.dist.php) and runcomposer cs:fix. - Adapt
name,description,homepage,keywordsandlicenseincomposer.json: they still describe the skeleton. - Fill in the
TODO:items inAGENTS.md. It refers to the Actra coding standard (actra/coding-standard, a dev dependency) and has a "Project-specific rules" section for your own rules. - Before the first deployment: copy
vendor/actra/coding-standard/templates/deploy.jsonto the project root, sethost(SSH alias) andpath(project root on the server), commit it and deploy withvendor/bin/deploy(tooling.md, section 8).
Structure
.env.php # environment settings (not committed)
public/
index.php # front controller: initializes yuf and defines the routes and the views
.htaccess # sends all requests to index.php
app/
view/frontend/ # view group "frontend" of the route "/"
IndexView.php # view class for / (registered in public/index.php)
html/index.html # content of /
templates/default.html # page layout around the content
view/auto/ # view group "auto" of the route "/auto/" (automatic view detection)
php/welcome.php # view class for /auto/ (found by file name, not registered)
html/welcome.html # content of /auto/ (default file of /auto/)
html/about.html # content of /auto/about.html (no view)
templates/default.html # page layout of this view group
error_docs/ # error pages (debug, not found, unauthorized, default)
cache/, logs/ # created at runtime (not committed)
AGENTS.md # instructions for developers and AI assistants (refers to the coding standard)
CLAUDE.md # makes Claude Code read AGENTS.md
.php-cs-fixer.dist.php # code style (rules of the coding standard)
phpstan.neon # static analysis (config of the coding standard)
tests/ # PHPUnit tests (phpunit.xml)
docs/ # documentation of the project (details linked from README.md)
Composer loads all classes: app\ from app/, tests\ from tests/ (PSR-4, the file name equals the class name).
.gitignore is an allowlist: add every new top-level file or directory (e.g. src/) there, otherwise it is not
committed; check with git status --ignored. Add new directories with PHP code to DIRECTORIES in
tests/Unit/StrictTypesTest.php as well.
Pages and views
public/index.php has two routes: / registers each view in a ViewMap, /auto/ finds the view by file name. How a
request is handled, how to add a page, when to use which route and optional features (login page, navigation, English
texts of yuf): docs/views.md.
Moving a project from the old Actra framework to this skeleton: follow the migration guide of yuf.
Checks
composer check
Runs the code style check, PHPStan and the PHPUnit tests. With DDEV: ddev composer check.
Production
- Keep
'debug' => false, and set your real domain(s) inallowedDomainsand a validlogEmailRecipientin.env.php. - Set
zend.exception_ignore_args=Onin the PHP configuration: stack traces then carry no arguments (passwords, tokens) into the error log. - Use PHP 8.5.12 or later (fixes the "php2shell" vulnerabilities CVE-2026-109618/109619) and set the request and
upload limits of yuf in
php.inior the PHP-FPM pool, e.g.session.upload_progress.enabled=0and, without upload forms,file_uploads=0andpost_max_size=2M(yuf: Request and upload limits). - Behind a reverse proxy or load balancer, let the web server set
REMOTE_ADDRto the client address (e.g. Apachemod_remoteip): yuf reads the client IP fromREMOTE_ADDRonly. - Build
vendor/without development tools and with an optimized autoloader:composer install --no-dev --optimize-autoloader. Composer is needed to build, not on the server. - On every deployment, reset the opcache (
opcache.validate_timestamps=0) and deleteapp/cache/v[0-9]*/: withoutdebug, changed templates are not compiled again. Notapp/cache/v*/: that also deletesapp/cache/values/.
Details: yuf: Production and yuf: Host and client IP address.
License
MIT, see LICENSE. composer create-project removes the LICENSE file from new projects: choose your own
license, add a LICENSE file if needed, and set it as license in composer.json and in the file header. Projects
under any license, including proprietary ones, may use yuf (MIT AND LGPL-2.1-only AND Apache-2.0, see
yuf: License).