Library / SDK
nunomaduro/skeleton-php avatar
nunomaduro/skeleton-php

Skeleton PHP: a Composer template with Pint, Rector, PHPStan and PEST wired up

⚡️ This package provides a wonderful PHP skeleton to start building your next package idea.

998 stars69 forksPHPMIT

At a glance

What is it?
nunomaduro/skeleton-php is a starting template for a PHP package, distributed on Packagist and installed with composer create-project. Its value is the toolchain, since code style, refactoring, static analysis and tests are already exposed as Composer scripts, but it also demands PHP 8.5 and ships without any tagged releases of its own.
Who is it for?
Skeleton PHP is worth using when you are starting a library and want a ready-wired toolchain, because the four commands are already exposed as Composer scripts and the configuration files are already in the tree.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One Composer command creates the project

The whole onboarding story fits in a single command. The package is installed from Packagist with composer create-project, and the README gives the invocation with the package name replaced at the end by your own.

bash
composer create-project nunomaduro/skeleton-php --prefer-source --remove-vcs PackageName

Two flags carry meaning here. --prefer-source asks Composer to take the package from source rather than from a dist archive, which is what you want when the point of the template is that you will edit it. --remove-vcs strips the version control metadata that came with the template, so the new project starts with a clean history and your own repository is the first commit.

The template is a package skeleton rather than an application skeleton. The repository has a src/ directory, a tests/ directory and a docs/ directory, which is the layout you want for something published to Packagist and consumed with Composer, not for something deployed as a web application.

PHP 8.5 is a hard floor, not a suggestion

The stated requirement is PHP 8.5 or later, and that single line decides whether the template is usable for you. Composer checks the platform requirement of the package before it copies anything, so on a machine with an older PHP the create-project command stops with a platform error rather than producing a project that fails later.

This is a real constraint for anyone still on 8.2 or 8.3, and for hosts where the PHP version is chosen by the hosting provider rather than by the project. The requirement is stated with a link to the PHP releases page, so it is meant to be read against the current version list.

The trade-off runs the other way too. A template that asks for the newest PHP can use modern language features in its own source and in the example code it ships, so you are not forced to write code that a two year old runtime can parse. The cost is that the generated project inherits that floor, and lowering it later means editing the platform requirement and rechecking every dependency in the tree.

Style, refactoring, types and tests are four Composer scripts

The part of this template that is worth more than the directory structure is the set of commands the README documents, one per tool. Keeping a modern codebase with Pint runs through composer lint.

bash
composer lint

Running refactors using Rector goes through composer refactor.

bash
composer refactor

Static analysis with PHPStan is composer test:types.

bash
composer test:types

Unit tests with PEST are composer test:unit.

bash
composer test:unit

And the entire test suite is one more script away.

bash
composer test

The naming is the design. Everything is behind a stable Composer script name, so the underlying tool can be swapped or upgraded without editing the command a contributor or a CI job has to remember. It also means the same command works locally and in automation, which is the property that makes a template stick.

The root files tell you which tools the project expects

The top level of the repository is a map of the toolchain, and it is worth reading before you generate anything. There is a phpstan.neon.dist file for static analysis configuration, a rector.php file for the refactoring rules, and a phpunit.xml.dist file for the test runner. Those three files exist because the four commands above need somewhere to read their settings from, and their presence in the template means you do not have to work out a sensible configuration before your first commit.

Alongside them sit a composer.json for the package definition and scripts, a .editorconfig for whitespace and indentation, and a .gitattributes. Documentation and process files are present as well, with a docs/ directory, a CHANGELOG.md, a CONTRIBUTING.md and a SECURITY.md, which tells you the template expects a published project with a disclosure route for security issues rather than a private script.

The .github/ directory holds the workflows, and the README carries a badge for the workflow status on the master branch pointing at a tests.yml workflow, so the same commands are expected to run on every push.

Versioning lives on Packagist, not in release tags

The repository publishes no GitHub releases, so there is no tag page to browse and no release notes attached to a version on the service. The documentation instead carries a Packagist badge for the latest version and one for total downloads, and Packagist is where the package is actually installed from, since the create-project command names the package on that registry.

In practice that means the changelog is the record of what changed. A CHANGELOG.md sits in the root of the template, and it is the file a consumer will read when a version bump appears on Packagist. The maintenance picture is otherwise straightforward: the last push to the repository was on 2026-10-13, the default branch is master, and the project is MIT licensed with the licence text in LICENSE.md.

One detail is worth flagging for anyone writing documentation for their own package. The homepage recorded for this package is a YouTube channel rather than a documentation site, which is a deliberate choice by the author and a reminder that a skeleton lets you set whatever metadata your project needs, including the fields you would rather leave out.

Editorial conclusion

Skeleton PHP is worth using when you are starting a library and want a ready-wired toolchain, because the four commands are already exposed as Composer scripts and the configuration files are already in the tree. It is the wrong choice for a project that must run on an older PHP, since the stated requirement is PHP 8.5 or later, and it is the wrong choice if you want a recorded release history, because the repository publishes no GitHub releases and keeps its history in CHANGELOG.md. Before you generate a project from it, read the composer.json scripts and the phpstan.neon.dist file, and check the last push date, which was 2026-10-13.

Frequently asked questions

How do I create a new PHP package from Skeleton PHP?

Run composer create-project nunomaduro/skeleton-php --prefer-source --remove-vcs PackageName, replacing the last argument with your package name. The --prefer-source flag keeps the source form of the template and --remove-vcs strips the original version control metadata.

Which PHP version does Skeleton PHP require?

The template states that it requires PHP 8.5 or later, and Composer checks that platform requirement before it copies the project, so create-project fails on an older PHP version.

What do the Composer scripts in Skeleton PHP do?

composer lint runs Pint to keep the codebase modern, composer refactor runs Rector, composer test:types runs PHPStan for static analysis, composer test:unit runs PEST for unit tests, and composer test runs the entire test suite.

Is Skeleton PHP licensed for commercial use?

Yes, it was created by Nuno Maduro under the MIT licence, with the licence text in the LICENSE.md file at the root of the repository.

Official sources

  1. Issues
  2. License: MIT
  3. nunomaduro/skeleton-php on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nunomaduro-skeleton-php.svg)](https://hysenlabs.com/projects/nunomaduro-skeleton-php)

Was this useful?