{"id":15296494,"url":"https://github.com/charcoalphp/charcoal","last_synced_at":"2026-03-13T01:34:27.977Z","repository":{"id":37248278,"uuid":"491937690","full_name":"charcoalphp/charcoal","owner":"charcoalphp","description":"Charcoal is a web-based tool box that adapts to all your project needs.","archived":false,"fork":false,"pushed_at":"2026-02-12T18:14:21.000Z","size":90979,"stargazers_count":8,"open_issues_count":17,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-02-20T08:50:15.027Z","etag":null,"topics":["charcoal","cms-framework","monorepo","php","php7","php8"],"latest_commit_sha":null,"homepage":"https://charcoal.locomotive.ca","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/charcoalphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-05-13T14:51:30.000Z","updated_at":"2025-04-11T20:23:07.000Z","dependencies_parsed_at":"2025-02-23T23:32:24.734Z","dependency_job_id":"4d5efb70-a3d2-4ba4-8a3f-af067e00b93b","html_url":"https://github.com/charcoalphp/charcoal","commit_stats":{"total_commits":6194,"total_committers":27,"mean_commits":"229.40740740740742","dds":0.6499838553438813,"last_synced_commit":"bd4083da103cf215cac5d3f0ebf5736ff8f4c4bb"},"previous_names":[],"tags_count":104,"template":false,"template_full_name":null,"purl":"pkg:github/charcoalphp/charcoal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charcoalphp%2Fcharcoal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charcoalphp%2Fcharcoal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charcoalphp%2Fcharcoal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charcoalphp%2Fcharcoal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/charcoalphp","download_url":"https://codeload.github.com/charcoalphp/charcoal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charcoalphp%2Fcharcoal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30453810,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T21:31:01.033Z","status":"ssl_error","status_checked_at":"2026-03-12T21:30:43.161Z","response_time":114,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["charcoal","cms-framework","monorepo","php","php7","php8"],"created_at":"2024-09-30T18:10:51.996Z","updated_at":"2026-03-13T01:34:27.959Z","avatar_url":"https://github.com/charcoalphp.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003cbr/\u003e\n    \u003cimg alt=\"Charcoal\" width=\"300\" src=\"assets/docs/images/charcoal-logo-full.svg\" /\u003e\n    \u003cbr/\u003e\n    by \u003ca href=\"https://locomotive.ca\"\u003eLocomotive\u003c/a\u003e 🚂\n\u003c/div\u003e\n\n---\n\n[![License][badge-license]](LICENSE)\n[![Latest Stable Version][badge-version]][charcoal-pkg]\n[![Uses Semantic Release with Conventional Commits][badge-semantic-release]][semantic-release]\n[![Commitizen-friendly][badge-commitizen]][commitizen]\n[![Supported PHP Version][badge-php]](composer.json)\n\nCharcoal is a web framework and content management system that adapts to all of\nyour project's needs.\n\nThis repository is a monorepo containing the entirety of the web framework.\nCharcoal can be used as a full stack framework or as standalone packages which\ncan be used independently.\n\n## Charcoal packages\n\nCore packages can be found in the [`packages`](packages/) directory.\n\n| Directory                           | Distribution          | Description                                                                           |\n|:------------------------------------|:----------------------|:--------------------------------------------------------------------------------------|\n| [`admin`](packages/admin)           | [charcoal/admin]      | The administration dashboard for Charcoal.                                            |\n| [`app`](packages/app)               | [charcoal/app]        | The web application layer (container, routing, controllers,…), based on [Slim][slim]. |\n| [`attachment`](packages/attachment) | [charcoal/attachment] | Provides support for working with relationships between models.                       |\n| [`cache`](packages/cache)           | [charcoal/cache]      | The cache layer, based on [Stash][tedivm/stash].                                      |\n| [`cms`](packages/cms)               | [charcoal/cms]        | Provides content management system (CMS) tools and extensions.                        |\n| [`config`](packages/config)         | [charcoal/config]     | The base configuration and entity layer most packages build upon.                     |\n| [`core`](packages/core)             | [charcoal/core]       | The model, repository, and database layer.                                            |\n| [`email`](packages/email)           | [charcoal/email]      | Provides support for sending emails, based on [PHPMailer][phpmailer].                 |\n| [`factory`](packages/factory)       | [charcoal/factory]    | Provides support for object creation (factory, builder, class resolution,…).          |\n| [`image`](packages/image)           | [charcoal/image]      | Provides support for image handling and manipulation.                                 |\n| [`object`](packages/object)         | [charcoal/object]     | Provides support for advanced modeling (routable, revisionable, authoriship,…).       |\n| [`property`](packages/property)     | [charcoal/property]   | The model metadata layer.                                                             |\n| [`queue`](packages/queue)           | [charcoal/queue]      | Provides support for building queues.                                                 |\n| [`translator`](packages/translator) | [charcoal/translator] | Provides support for internationalization, based on [Symfony][symfony/translation].   |\n| [`ui`](packages/ui)                 | [charcoal/ui]         | Provides layout tools (dashboards, layouts, forms, menus,…).                          |\n| [`user`](packages/user)             | [charcoal/user]       | The user modeling, authentication, and authorization layer.                           |\n| [`view`](packages/view)             | [charcoal/view]       | The view layer with support for [Mustache][mustache], [Twig][twig],…                  |\n\n\n## Installation\n\nThe preferred (and only supported) method is with Composer:\n\n```shell\ncomposer require charcoal/charcoal\n```\n\nTo start from a working skeleton:\n\n```shell\ncomposer create-project charcoal/boilerplate\n```\n\n### Standalone packages\n\nThe Charcoal framework is split into standalone packages which can be used\nindependently. For example, a project might not need an administration panel,\na queue system, or to send emails.\n\n```shell\ncomposer require charcoal/app charcoal/api custom/admin \n```\n\n### Migrate a project to `charcoal/charcoal`\n\nThe following will aide with converting a project from\n`locomotivemtl/charcoal-*` to `charcoal/*`.\n\n\u003e ℹ️ Previously all core packages maintained their own version numbering independently.\n\u003e\n\u003e The monorepo framework uses a shared version number for all core packages\n\u003e for consistent and expected interoperability.\n\n\u003e ℹ️ The contrib packages continue to maintain their existing independent version numbering.\n\n\u003cdetails\u003e\n    \u003csummary\u003eOption A — If you want to replace all packages with the full-stack framework package:\u003c/summary\u003e\n\n1. Remove requirements for core packages (`locomotivemtl/charcoal-*`)\n   in your `composer.json` file.\n2. Replace requirements for contrib packages  (`locomotivemtl/charcoal-contrib-*`),\n   in your `composer.json` file, with equivalents from [`charcoal/contrib-*`][charcoal-org].\n3. Run `composer require charcoal/charcoal` to install the framework.\n4. Run `composer update` to ensure all requirements are up-to-date.\n5. Run the following migration script:\n\n   ```shell\n   ./vendor/charcoal/charcoal/build/script/migrate-project\n   ```\n   \n   The `migrate-project` script will update all metadata paths in your project's\n   configuration files. Afterwards, it will edit or create a `.env` environment\n   variable file with the key `PACKAGES_PATH` set to:\n   `vendor/charcoal/charcoal/packages`.\n\n   This allows the `%packages.path%` string template to expand to the packages\n   location within `charcoal/charcoal`, otherwise it will lead in the `vendor`\n   directory.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eOption B — If you want to replace all packages with new standalone packages:\u003c/summary\u003e\n\n1. Replace requirements for core packages (`locomotivemtl/charcoal-*`),\n   in your `composer.json` file.\n2. Replace requirements for contrib packages  (`locomotivemtl/charcoal-contrib-*`),\n   in your `composer.json` file, with equivalents from [`charcoal/contrib-*`][charcoal-org].\n3. Run `composer require charcoal/config charcoal/core…` to install the packages.\n4. Run `composer update` to ensure all requirements are up-to-date.\n5. Replace occurrences of `vendor/locomotivemtl/charcoal-*` in your configuration\n   files with `vendor/charcoal/*`.\n\n\u003c/details\u003e\n\n### Dependencies\n\n#### ⚠️ Required\n\n* [PHP](https://php.net) 7.4 or 8.0\n\n## ⚙️ Configuration\n\n[TODO]\n\n## Usage\n\n[TODO]\n\n## Development\n\nDevelopment is made in a seperate branch from the `main` branch. \n\n\u003e ⚠️ The `main` branch is protected and doesn't allow pushing changes directly into.\n\nTo install the development environment:\n\n```shell\ncomposer install\n```\n\nTo run the scripts (phplint, phpcs, and phpunit):\n\n```shell\ncomposer test\n```\n\n### Commit message format\n\nCharcoal uses [semantic-release] to handle the release process.\n\nIt uses the commit messages to determine the consumer impact of changes\nin the codebase. Following formalized conventions for commit messages,\n[semantic-release] automatically determines the next [Semantic Version][semver]\nnumber, generates a changelog, and publishes the release.\n\nThe current setup uses the [Conventional Commits][conventional-commits] for\ncommit messages. You can consult it for further information.\n\nThis repository is [Commitizen][commitizen] friendly and is configured to use\nthe [Conventional Commits][conventional-commits] standard, therfore you can\ninstall it globally to ease the process of writting commits.\n\nAlternatively, there is some code editor plugins that can help with the creation\nof conventional commits:\n\n* `vscode`\n    * [VSCode Conventional Commits](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits#:~:text=You%20can%20access%20VSCode%20Conventional,on%20the%20Source%20Control%20menu.)\n* `phpstrom`\n    * [Conventional Commit](https://plugins.jetbrains.com/plugin/13389-conventional-commit)\n    * [Git Commit Template](https://plugins.jetbrains.com/plugin/9861-git-commit-template)\n\nHere is an example of release types based on some commit messages:\n\n* Patch (Fix) release:\n\n    ```yaml\n    fix(pencil): stop graphite breaking when too much pressure applied\n    ```\n\n* Minor (Feature) release:\n\n    ```yaml\n    feat(pencil): add 'graphiteWidth' option\n    ```\n\n* Major (Breaking) release:\n\n    ```yaml\n    perf(pencil): remove graphiteWidth option\n\n    BREAKING CHANGE: The graphiteWidth option has been removed.\n    The default graphite width of 10mm is always used for performance reasons.\n    ```\n\n    \u003e ✍🏻 Note that the `BREAKING CHANGE: ` token must be in the foot\n    \u003e of the commit.\n\n### Development guidelines\n\nDevelopment should be branch-based and commit messages should following\nConventional Commits.\n\n| Steps                                                                                                                                     | Notes                                                                                                                                                                                                                                       |\n|:------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| 1. Branch from `main` or checkout `develop`                                                                                               | Make sure the `develop` branch is up to date with `main`. You should favor a new branch if the needed work time is not short. On a personal branch, favor using the `rebase` method to keep up to date with the `main` branch               |\n| 2. Do your thing                                                                                                                          | Write some code                                                                                                                                                                                                                             |\n| 3. Commit your changes using the [Conventional Commits][conventional-commits] standard                                                    | You can use [Commitizen][commitizen] or a code editor plugin to help with this process. See the [Commit message format](#commit-message-format) section for more information.                                                               |\n| 4. Push to a remote branch and run the `./create-pr` script.                                                                              | Using the `./create-pr` to script to create a PR is not mandatory. You could always create it manually, but the script will be faster, generates a changelog message and assigns a reviewer from the [@charcoalphp/reviewers][gh-reviewers] |\n| 5. Wait for a review and a merge to happen                                                                                                | Drink ☕️ and eat 🍕                                                                                                                                                                                                                         |\n| 6. After the merge is done, github workflows will handle the release process, tagging, updating dependencies and updatting the changelog. | Good Job ! 🤘                                                                                                                                                                                                                               |\n\n\n### Maintenance and automations\n\nSymplify's [MonorepoBuilder][symplify/monorepo-builder] is used to handle the\nconformity between the core repo and it's packages. It will sync `composer.json`\nfiles and packages versions.\n\n[TODO] Semantic release config in .releaserc\n\n[TODO] [Conventional Commits][conventional-commits]\n\n[TODO] [Commitizen][commitizen]\n\n### Development Dependencies\n\n* [symplify/monorepo-builder]\n    * Keeps packages versions in sync.\n    * Config is located in [**monorepo-builder**](monorepo-builder.php).\n      It allows to define more dependencies\n* [semantic-release]\n    * Handle the release process from a [Github action](https://github.com/cycjimmy/semantic-release-action).\n\n### Development History\n\nThis monorepo was created with a many to mono aproach using this guide and tool:\n\n* [hraban/tomono](https://github.com/hraban/tomono)\n\n### Github Actions\n\n| Actions                                                           | Trigger                        | Description                                                                                                                                                                                                        |\n|:------------------------------------------------------------------|:-------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [Release](.github/workflows/release.yml)                          | Push on supported branches     | Trigger a Github release using [semantic-release](https://github.com/marketplace/actions/action-for-semantic-release)                                                                                              |\n| [Split Monorepo](.github/workflows/split_monorepo.yml)            | Release on `main`              | The split action splits the packages into individual repositories. Only triggered when a tag is pushed. Based on [symplify/monorepo-split-github-action](https://github.com/symplify/monorepo-split-github-action) |\n| [Update Changelog](.github/workflows/update-changelog.yml)        | Release on `main`              | Uses [changelog-updater-action](https://github.com/stefanzweifel/changelog-updater-action) to update the changelog of the `main` branch                                                                            |\n\n### Scripts\n\n#### __create-pr__\n\nThis script streamlines the process of creating a Pull Request. When your branch is ready to be pulled into the `main` or \nanother `[target]` branch, this tool will generate it for you, request review form [@charcoalphp/reviewers][gh-reviewers] and add\na beautiful and readable release note generated from the differences between the two breanches. \n\nDocumentation\n\n```shell\nDescription\n  Create a pull request on the github repository on the requested branch.\n  Default branch: main\n\nUsage\n  ./create-pr\n\nOptions\n  -b, --base          The base branch to merge into for the pull request. [Default: main]\n  -h, --head          The branch to compare against the base branch. [Default: The current branch]\n```\n\nExample\n```shell\n# target: the target branch for the pull request. Defaults to [main]\n./create-pr -b main -h user:feat-branch\n```\n\n#### __create-release-notes__ (_optional tool_)\n\nThis script generates release notes on request, returning a changelog based on the requested `range of commits` or `branches`.\n\nDocumentation:\n\n```shell\n./build/script/create-release-notes --help\n```\n\nExample:\n\n```shell\n./build/script/create-release-notes -g --from main\n```\n\nOutput:\n\n\u003e ## Changes:\n\u003e \n\u003e ### Features\n\u003e \n\u003e * **create-pr:** add a script to trigger a pull request on the remote ([3016115](https://github.com/charcoalphp/charcoal/commit/3016115d4f7c919261c54e3a17ae6c36552e532a))\n\u003e \n\u003e \n\u003e ### Bug Fixes\n\u003e \n\u003e * **create-pr:** remove Personal access token from script and replace with `$GITHUB_TOKEN` instead ([f2aaac6](https://github.com/charcoalphp/charcoal/commit/f2aaac6dbd630f0f8fa759e49f9f41c957e3868a))\n\u003e * **package:** add missing semantic-release plugin ([59bd1b1](https://github.com/charcoalphp/charcoal/commit/59bd1b1798e4e7b6bf874c7ba8ecbae19d76342b))\n\n## Contributing\n\nEveryone interacting with Charcoal is expected to follow\nthe [code of conduct](https://github.com/charcoalphp/.github/blob/main/CODE_OF_CONDUCT.md).\n\nPlease see our [contribution guide](https://github.com/charcoalphp/.github/blob/main/CONTRIBUTING.md)\non how to contribute to Charcoal.\n\nIf you are tying to report a possible security vulnerability in Charcoal,\nplease see our [security policy](https://github.com/charcoalphp/charcoal/security/policy) for more information.\n\n## ✍🏻 Authors\n\n* [Locomotive][locomotive] 🚂\n* [Mathieu Ducharme](mailto:mat@locomotive.ca) 👨🏻‍💻\n* [Chauncey McAskill](mailto:chauncey@locomotive.ca) 👨🏻‍💻\n* [Joel Alphonso](mailto:joel@locomotive.ca) 👨🏻‍💻\n* [Dominic Lord](mailto:dom@locomotive.ca) 👨🏻‍💻\n* [Benjamin Roch](mailto:ben@locomotive.ca) 👨🏻‍💻\n\n## 🎉 Contributors\n\n[![List of contributors](https://contrib.rocks/image?repo=charcoalphp/charcoal)][gh-contributors]\n\nMade with [contrib.rocks](https://contrib.rocks).\n\n## Changelog\n\nView [CHANGELOG](CHANGELOG.md).\n\nThe changelog is compliant with [*Keep a Changelog*][keepachangelog] and is autogenerated from autoreleases.\n\n## License\n\nCharcoal is licensed under the MIT license. See [LICENSE](LICENSE) for details.\n\n[charcoal-org]:              https://github.com/charcoalphp\n[charcoal-pkg]:              https://packagist.org/packages/charcoal/charcoal\n[charcoal/admin]:            https://github.com/charcoalphp/admin\n[charcoal/app]:              https://github.com/charcoalphp/app\n[charcoal/attachment]:       https://github.com/charcoalphp/attachment\n[charcoal/cache]:            https://github.com/charcoalphp/cache\n[charcoal/charcoal]:         https://github.com/charcoalphp/charcoal\n[charcoal/cms]:              https://github.com/charcoalphp/cms\n[charcoal/config]:           https://github.com/charcoalphp/config\n[charcoal/core]:             https://github.com/charcoalphp/core\n[charcoal/email]:            https://github.com/charcoalphp/email\n[charcoal/factory]:          https://github.com/charcoalphp/factory\n[charcoal/image]:            https://github.com/charcoalphp/image\n[charcoal/object]:           https://github.com/charcoalphp/object\n[charcoal/property]:         https://github.com/charcoalphp/property\n[charcoal/queue]:            https://github.com/charcoalphp/queue\n[charcoal/translator]:       https://github.com/charcoalphp/translator\n[charcoal/ui]:               https://github.com/charcoalphp/ui\n[charcoal/user]:             https://github.com/charcoalphp/user\n[charcoal/view]:             https://github.com/charcoalphp/view\n\n[commitizen]:                https://github.com/commitizen/cz-cli\n[conventional-commits]:      https://www.conventionalcommits.org/en/v1.0.0/\n[gh-contributors]:           https://github.com/charcoalphp/charcoal/graphs/contributors\n[gh-reviewers]:              https://github.com/orgs/charcoalphp/teams/reviewers\n[keepachangelog]:            https://keepachangelog.com/en/1.0.0/\n[locomotive]:                https://locomotive.ca\n[mustache]:                  https://github.com/bobthecow/mustache.php\n[phpmailer]:                 https://github.com/PHPMailer/PHPMailer\n[semantic-release]:          https://github.com/semantic-release/semantic-release\n[semver]:                    https://semver.org\n[slim]:                      https://github.com/slimphp/slim\n[symfony/translation]:       https://github.com/symfony/translation\n[symplify/monorepo-builder]: https://github.com/symplify/monorepo-builder\n[tedivm/stash]:              https://github.com/tedious/Stash\n[twig]:                      https://github.com/twigphp/Twig\n\n[badge-commitizen]:          https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square\n[badge-license]:             https://img.shields.io/packagist/l/charcoal/charcoal.svg?style=flat-square\n[badge-php]:                 https://img.shields.io/packagist/php-v/charcoal/charcoal?style=flat-square\u0026logo=php\n[badge-semantic-release]:    https://img.shields.io/badge/semantic--release-conventionalcommits-e10079?logo=semantic-release\u0026style=flat-square\n[badge-version]:             https://img.shields.io/packagist/v/charcoal/charcoal.svg?style=flat-square\u0026logo=packagist\n\n[psr-1]:  https://www.php-fig.org/psr/psr-1/\n[psr-2]:  https://www.php-fig.org/psr/psr-2/\n[psr-3]:  https://www.php-fig.org/psr/psr-3/\n[psr-4]:  https://www.php-fig.org/psr/psr-4/\n[psr-6]:  https://www.php-fig.org/psr/psr-6/\n[psr-7]:  https://www.php-fig.org/psr/psr-7/\n[psr-11]: https://www.php-fig.org/psr/psr-11/\n[psr-12]: https://www.php-fig.org/psr/psr-12/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharcoalphp%2Fcharcoal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharcoalphp%2Fcharcoal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharcoalphp%2Fcharcoal/lists"}