PHPackages                             roadiz/skeleton - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. roadiz/skeleton

ActiveProject[Framework](/categories/framework)

roadiz/skeleton
===============

v2.7.2(2mo ago)192752mitPHPPHP &gt;=8.3CI passing

Since Jul 4Pushed 2mo ago3 watchersCompare

[ Source](https://github.com/roadiz/skeleton)[ Packagist](https://packagist.org/packages/roadiz/skeleton)[ RSS](/packages/roadiz-skeleton/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelogDependencies (44)Versions (75)Used By (0)

roadiz/skeleton
===============

[](#roadizskeleton)

**Headless API project skeleton built on Roadiz v2+**

[![Run test status](https://github.com/roadiz/skeleton/actions/workflows/run-test.yml/badge.svg?branch=develop)](https://github.com/roadiz/skeleton/actions/workflows/run-test.yml/badge.svg?branch=develop)

### Install

[](#install)

```
COMPOSER_MEMORY_LIMIT=-1 composer create-project roadiz/skeleton my-website
```

Customize configuration by copying `.env` to `.env.local`:

```
cp .env .env.local
```

Make sure to tell docker-compose to use `.env.local` if you are changing variables used for containers initialization (MySQL / Solr / SMTP credentials). Roadiz app will read `.env` then will override vars with your `.env.local`. That's why `.env` file is committed in Git repository, and it MUST not contain any secret.

If Composer complains about memory limit issue, just prefix with `COMPOSER_MEMORY_LIMIT=-1`.

Edit your `.env.local` and `docker-compose.yml` files according to your local environment.

```
# Copy override file to customize your local environment
cp compose.override.yml.dist compose.override.yml
# Do not forget to add your COMPOSER_DEPLOY_TOKEN and COMPOSER_DEPLOY_TOKEN_USER
# in compose.override.yml to configure your container to fetch private repositories.
docker compose build
docker compose up -d --force-recreate
```

Then wait for your services to initialize, especially your *database* could take several seconds to initialize (filesystem, database and user creation).

When you're ready you can check that *Symfony* console responds through your Docker service:

```
docker compose exec app bin/console
```

#### Using Docker for development

[](#using-docker-for-development)

If you want to ensure that your local environment is as close as possible to your production environment, you should use Docker. This skeleton comes with development and production `Dockerfile` configurations. So you will avoid troubles with installing PHP extensions, Solr, Varnish, Redis, MySQL, etc. You can also use `composer` inside your app container to install your dependencies.

```
# This command will run once APP container to install your dependencies without starting other services
docker compose run --rm --no-deps --entrypoint= app composer install -o
```

To access your app services, you will have to expose ports locally in your `compose.override.yml` file. Copy `compose.override.yml.dist` to `compose.override.yml` file to override your `compose.yml` file and expose your app container ports for local development:

```
# Expose all services default ports for local development
services:
    db:
        ports:
            - ${PUBLIC_DB_PORT}:3306/tcp
    nginx:
        ports:
            - ${PUBLIC_NGINX_PORT}:80/tcp
    mailer:
        ports:
            - ${PUBLIC_MAILER_PORT}:8025/tcp
    varnish:
        ports:
            - ${PUBLIC_VARNISH_PORT}:80/tcp
    redis:
        ports:
            - ${PUBLIC_REDIS_PORT}:6379/tcp
    pma:
        ports:
            - ${PUBLIC_PMA_PORT}:80/tcp
    # If you depend on private Gitlab repositories, you must use a deploy token and username
    #app:
    #    build:
    #        args:
    #            UID: ${UID}
    #            COMPOSER_DEPLOY_TOKEN: xxxxxxxxxxxxx
    #            COMPOSER_DEPLOY_TOKEN_USER: "gitlab+deploy-token-1"
```

### Generate [Symfony secrets](https://symfony.com/doc/current/configuration/secrets.html)

[](#generate-symfony-secrets)

When you run `composer create-project` first time, following command should have been executed automatically:

```
docker compose exec app bin/console secrets:generate-keys
```

Then generate secrets values for your configuration variables such as `APP_SECRET` or `JWT_PASSPHRASE`:

```
docker compose exec app bin/console secrets:set JWT_PASSPHRASE --random
docker compose exec app bin/console secrets:set APP_SECRET --random
```

**Make sure your remove any of these variables from your `.env` and `.env.local` files**, it would override your secrets (empty values for example), and lose all benefits from encrypting your secrets.

### Generate JWT private and public keys

[](#generate-jwt-private-and-public-keys)

Use built-in command to generate your key pair (following command should have been executed automatically at `composer create-project`):

```
docker compose exec app bin/console lexik:jwt:generate-keypair
```

### Install database

[](#install-database)

Use `make install` command to install your database schema and fixtures.

Or manually:

```
# Create Roadiz database schema
docker compose exec app bin/console doctrine:migrations:migrate
# Migrate any existing data types
docker compose exec app bin/console app:install
# Install base Roadiz fixtures, roles and settings
docker compose exec app bin/console install
# Clear cache
docker compose exec app bin/console cache:clear
```

Before accessing the application, you need to create an admin user. Use the following command to create a user account:

```
# Create your admin account with the specified username and email
export EMAIL="username@roadiz.io"
docker compose exec app bin/console users:create -m $EMAIL -b -s $EMAIL
# By default, a random password will be generated for the new user.
# If you want to set a custom password, you can add the -p option followed by your desired password
```

### Manage Node-types

[](#manage-node-types)

Node-types can be managed through back-office interface or by editing JSON files in `src/Resources/node-types` directory. If you edit JSON files manually you need to synchronize your database with these files and generate Doctrine Migrations if this leads to database schema changes.

#### Migrate node-types

[](#migrate-node-types)

When you direct update the `node-types` JSON files, you need to add them into `src/Resources/config.yml`and run the following command to update the database:

```
make migrate
```

This command will **update PHP entities** and **create a Doctrine migration** file if necessary.

#### Apply node-type migration

[](#apply-node-type-migration)

When you pull the project and just want to sync your local node-types, you need to apply the migration:

```
make update
```

This will **only load node-types** that are not already in the database. But it won't create any migration. This is the same script that is executed when you run `make install` and in your docker image entrypoint.

### Features

[](#features)

- Configured to be used in headless mode with *API Platform*
- Configured with *lexik/jwt-authentication-bundle*
- All-Docker development and production environments
- Supervisor daemon for execution symfony/messenger consumers
- Solr and Varnish services right out-the-box
- Gitlab CI ready
- Use *phpcs* and *phpstan* to ensure code-smell and static analysis
- Packed with 4 *node-types*: `Menu`, `MenuLink` in order to create automatic menus in your `/api/common_content` response and `Page` and `AliasBlock` as a basic page and alias management system.

#### Common content endpoint

[](#common-content-endpoint)

`/api/common_content` endpoint is meant to expose common data about your website. You can fetch this endpoint once in your website frontend, instead of embedding the same data in each web response. `menus` entry will automatically hold any root-level `Menu` tree-walker.

```
{
    "@context": "/api/contexts/CommonContent",
    "@id": "/api/common_content?id=unique",
    "@type": "CommonContent",
    "home": {
        "@id": "/api/pages/1",
        "@type": "Page",
        "title": "home",
        "publishedAt": "2021-09-09T02:23:00+02:00",
        "node": {
            "@id": "/api/nodes/1",
            "@type": "Node",
            "nodeName": "home",
            "visible": true,
            "tags": []
        },
        "translation": {
            "@id": "/api/translations/1",
            "@type": "Translation",
            "name": "English",
            "defaultTranslation": true,
            "available": true,
            "locale": "en"
        },
        "slug": "home",
        "url": "/"
    },
    "head": {
        "@type": "NodesSourcesHead",
        "googleAnalytics": null,
        "googleTagManager": null,
        "matomoUrl": null,
        "matomoSiteId": null,
        "siteName": "Roadiz dev website",
        "metaTitle": "Roadiz dev website",
        "metaDescription": "Roadiz dev website",
        "policyUrl": null,
        "mainColor": null,
        "facebookUrl": null,
        "instagramUrl": null,
        "twitterUrl": null,
        "youtubeUrl": null,
        "linkedinUrl": null,
        "homePageUrl": "/",
        "shareImage": null
    },
    "menus": {
        "mainMenuWalker": {
            "@type": "MenuNodeSourceWalker",
            "children": [],
            "item": { ... },
            "childrenCount": 0,
            "level": 0,
            "maxLevel": 3
        }
    }
}
```

### Versioning

[](#versioning)

Make sure your `.env` file does not contain any sensitive data as it must be added to your repository: `git add --force .env`in order to be overridden by `.env.local` file. Sensitive and local data must be filled in `.env.local` which is git-ignored.

### Conventional commits

[](#conventional-commits)

This project uses conventional commits to automate the release process and *changelog* generation with [git-cliff](https://github.com/orhun/git-cliff). A `cliff.toml` configuration file is already provided in this skeleton.

#### Generate a CHANGELOG file

[](#generate-a-changelog-file)

```
git cliff -o CHANGELOG.md
```

#### Before releasing

[](#before-releasing)

- With a known tag ```
    git cliff -o CHANGELOG.md --tag 1.0.0
    ```
- Without knowing tag, let `git cliff` find the right version ```
    git cliff -o CHANGELOG.md --bump
    ```

### Credits

[](#credits)

This skeleton uses  script to wait for MySQL readiness before launching app entrypoint.

###  Health Score

53

—

FairBetter than 97% of packages

Maintenance86

Actively maintained with recent releases

Popularity23

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 95.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~19 days

Recently: every ~53 days

Total

71

Last Release

66d ago

PHP version history (5 changes)2.0.0PHP &gt;=7.4

v2.1.0PHP &gt;=8.0

v2.2.0PHP &gt;=8.1

v2.3.0PHP &gt;=8.2

v2.6.0PHP &gt;=8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/380026?v=4)[Ambroise Maupate](/maintainers/ambroisemaupate)[@ambroisemaupate](https://github.com/ambroisemaupate)

---

Top Contributors

[![ambroisemaupate](https://avatars.githubusercontent.com/u/380026?v=4)](https://github.com/ambroisemaupate "ambroisemaupate (581 commits)")[![eliot488995568](https://avatars.githubusercontent.com/u/72140926?v=4)](https://github.com/eliot488995568 "eliot488995568 (30 commits)")

---

Tags

bundlecmssymfony

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/roadiz-skeleton/health.svg)

```
[![Health](https://phpackages.com/badges/roadiz-skeleton/health.svg)](https://phpackages.com/packages/roadiz-skeleton)
```

###  Alternatives

[oro/platform

Business Application Platform (BAP)

644134.8k84](/packages/oro-platform)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[thelia/thelia

Thelia is an ecommerce CMS.

8715.1k](/packages/thelia-thelia)[contao/manager-bundle

Provides the Contao Managed Edition

181.3M61](/packages/contao-manager-bundle)[forumify/forumify-platform

121.8k11](/packages/forumify-forumify-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
