{"id":110,"date":"2026-11-02T08:00:00","date_gmt":"2026-11-02T07:00:00","guid":{"rendered":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/"},"modified":"2026-10-16T14:00:13","modified_gmt":"2026-10-16T12:00:13","slug":"composer-for-typo3-projects-path-repos-platform-and-audit","status":"publish","type":"post","link":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/","title":{"rendered":"Composer for TYPO3 projects: path repos, platform and audit"},"content":{"rendered":"<p>Most TYPO3 projects I see during upgrades have the same Composer story. The core and the third-party extensions come from Packagist, fine. But the sitepackage and the two or three project extensions sit somewhere in <code>public\/typo3conf\/ext\/<\/code>, committed directly, outside Composer. They have no version, no declared dependencies, and nobody can tell which core versions they support. Then the upgrade starts, and you find out the hard way.<\/p>\n<p>When I moved hoja.in from TYPO3 7.6 classic mode to a fresh 14.3 Composer project this year, I set up the Composer part so that the next upgrade is easier. These are the four pieces.<\/p>\n<h2>1. Your own extensions as path packages<\/h2>\n<p>A path repository tells Composer: packages can also be found in these local folders. Each extension gets its own <code>composer.json<\/code> with a name, a type and its requirements. This is the real root <code>composer.json<\/code> of hoja.in, shortened:<\/p>\n<pre><code class=\"language-json\">{\n    \"name\": \"harvisoft\/myport\",\n    \"type\": \"project\",\n    \"repositories\": [\n        {\n            \"type\": \"path\",\n            \"url\": \"Source\/Extension\/*\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^8.2\",\n        \"harvisoft\/sitepackage\": \"@dev\",\n        \"typo3\/cms-core\": \"^14.3\",\n        \"typo3\/cms-form\": \"^14.3\"\n    },\n    \"config\": {\n        \"platform\": {\n            \"php\": \"8.4\"\n        },\n        \"sort-packages\": true\n    },\n    \"minimum-stability\": \"stable\",\n    \"prefer-stable\": true\n}<\/code><\/pre>\n<p>Many projects use <code>packages\/*<\/code> as the folder name; I used <code>Source\/Extension\/*<\/code>. The name does not matter, the glob does: every folder with a <code>composer.json<\/code> below it becomes an installable package. Composer symlinks it into <code>vendor\/<\/code> (on hoja.in, <code>vendor\/harvisoft\/sitepackage<\/code> points to <code>..\/..\/Source\/Extension\/sitepackage\/<\/code>), and the TYPO3 Composer installers make it an active extension.<\/p>\n<p>The extension&#8217;s own <code>composer.json<\/code> declares what it really needs. For the hoja.in sitepackage that is PHP 8.2, <code>typo3\/cms-core<\/code>, <code>cms-fluid-styled-content<\/code>, <code>cms-form<\/code> and <code>cms-frontend<\/code>, all <code>^14.3<\/code>, plus the <code>extra.typo3\/cms.extension-key<\/code> <code>sitepackage<\/code>. Now the next upgrade has a clear signal: when you raise the core to v15, Composer refuses until the sitepackage says it supports v15. That is the point. The refusal is a to-do list.<\/p>\n<h3>The @dev warning<\/h3>\n<p><code>composer validate<\/code> on hoja.in is honest with me:<\/p>\n<pre><code class=\"language-text\">.\/composer.json is valid, but with a few warnings\n# General warnings\n- require.harvisoft\/sitepackage : unbound version constraints (@dev) should be avoided<\/code><\/pre>\n<p>The path package has no version, so Composer gives it a dev version and the root needs <code>@dev<\/code> to accept it. If you run <code>composer validate --strict<\/code> in CI, warnings fail the job. The cleaner way is to give the path package a version through the repository&#8217;s <code>versions<\/code> option and require it with a normal constraint:<\/p>\n<pre><code class=\"language-json\">\"repositories\": [\n    {\n        \"type\": \"path\",\n        \"url\": \"Source\/Extension\/*\",\n        \"options\": {\n            \"versions\": {\n                \"harvisoft\/sitepackage\": \"1.0.0\"\n            }\n        }\n    }\n],\n\"require\": {\n    \"harvisoft\/sitepackage\": \"^1.0\"\n}<\/code><\/pre>\n<p>That is on my list for hoja.in; today it still says <code>@dev<\/code>.<\/p>\n<h2>2. config.platform.php: resolve for production, not for your laptop<\/h2>\n<p>Composer resolves dependencies for the PHP version it runs on, unless you tell it otherwise. DDEV runs PHP 8.4 for hoja.in. If the hosting ran 8.2 and some package had a newer release that needs 8.3, my lock file would contain it, and production would break on the first <code>composer install<\/code>.<\/p>\n<p><code>config.platform.php<\/code> fakes the PHP version for resolution. hoja.in pins it to 8.4, the version the hosting must provide. The runbook has a warning next to it: lower it only together with a fresh <code>composer update<\/code>, because the setting changes what gets resolved, not what is already in the lock file.<\/p>\n<p>Two related habits:<\/p>\n<ul>\n<li>Never use <code>--ignore-platform-reqs<\/code> to &#8220;make it work&#8221;. It produces a lock file for a PHP version nobody runs. My migration plugin&#8217;s guard hook denies it for the AI agent, and I wish I had a hook for myself sometimes.<\/li>\n<li>On the server, run <code>composer check-platform-reqs --lock<\/code> before switching. It compares the lock file&#8217;s requirements with the PHP binary and extensions that are really there.<\/li>\n<\/ul>\n<h2>3. composer audit in CI<\/h2>\n<p><code>composer audit<\/code> checks your packages against the security advisories that Packagist knows, including the TYPO3 security advisories for core and extensions. It needs no extra tool:<\/p>\n<pre><code class=\"language-bash\">composer audit --locked --no-dev\ncomposer audit --locked --format=json &gt; audit.json<\/code><\/pre>\n<p><code>--locked<\/code> audits the lock file instead of the installed <code>vendor\/<\/code>, which is what you want in CI. <code>--no-dev<\/code> skips dev-only packages if you only care about what goes to production. The command exits with a non-zero code when it finds something, so a pipeline step is one line. A GitHub Actions job could look like this:<\/p>\n<pre><code class=\"language-yaml\">jobs:\n  composer:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - uses: shivammathur\/setup-php@v2\n        with:\n          php-version: '8.4'\n      - run: composer validate --strict\n      - run: composer audit --locked<\/code><\/pre>\n<p>Run it on a schedule too, not only on push. A project that nobody touches for three months still gets new advisories.<\/p>\n<h2>4. Abandoned packages during an upgrade<\/h2>\n<p>Packagist lets maintainers mark a package as abandoned, optionally with a replacement. <code>composer audit<\/code> reports abandoned packages as well, and the option <code>--abandoned<\/code> decides what happens: <code>ignore<\/code>, <code>report<\/code> or <code>fail<\/code>. The project default lives in <code>config.audit.abandoned<\/code>. In the Composer version of my DDEV container (2.10.3), <code>composer config audit<\/code> shows <code>\"abandoned\":\"fail\"<\/code>, so an abandoned package fails the audit.<\/p>\n<p>During an upgrade, abandoned and incompatible packages are the real blockers. My routine:<\/p>\n<ol>\n<li>Ask Composer directly what blocks the target: <code>composer why-not typo3\/cms-core \"^14.3\"<\/code> lists every package whose constraints prevent it.<\/li>\n<li>For each blocker, check Packagist and the repository: is there a release for the target, a maintained fork, an open pull request?<\/li>\n<li>If not, decide between replacing and dropping. Write the decision down with a reason.<\/li>\n<\/ol>\n<p>For hoja.in the blockers were older than Composer in that project, because 7.6 ran in classic mode: powermail had no v14 release, so the contact form moved to the core form framework; realurl was replaced by site configuration and slugs; flux, fluidpages and vhs were replaced by backend layouts and PAGEVIEW. Every one of those is a line in the migration ledger, with the reason. If an extension is abandoned and you still need it for a while, set <code>--abandoned=report<\/code> for that run and keep a ticket open, rather than switching the check off for good.<\/p>\n<h2>Checklist<\/h2>\n<ul>\n<li>Every own extension is a path package with its own <code>composer.json<\/code>.<\/li>\n<li>Real version constraints instead of <code>@dev<\/code>, so <code>composer validate --strict<\/code> passes.<\/li>\n<li><code>config.platform.php<\/code> matches production.<\/li>\n<li><code>composer audit --locked<\/code> on every push and on a schedule.<\/li>\n<li>Blockers and replacements written down before the upgrade starts.<\/li>\n<\/ul>\n<p>Feedbacks are the champion&#8217;s breakfast. Drop a comment if your setup looks different and why.<\/p>\n<h2>Further reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/getcomposer.org\/doc\/05-repositories.md#path\">Composer: path repositories<\/a><\/li>\n<li><a href=\"https:\/\/getcomposer.org\/doc\/06-config.md#platform\">Composer: config.platform<\/a><\/li>\n<li><a href=\"https:\/\/getcomposer.org\/doc\/03-cli.md#audit\">Composer: the audit command<\/a><\/li>\n<li><a href=\"https:\/\/docs.typo3.org\/m\/typo3\/guide-installation\/main\/en-us\/Index.html\">TYPO3 installation and upgrade guide<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Local extensions belong in Composer too: a path repository for your own extensions, config.platform.php for production, composer audit in CI and abandoned packages.<\/p>\n","protected":false},"author":1,"featured_media":111,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[26,45,43,5],"class_list":["post-110","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops-tooling","tag-composer","tag-devops","tag-security","tag-typo3"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Composer for TYPO3: path repos, platform and audit<\/title>\n<meta name=\"description\" content=\"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Composer for TYPO3: path repos, platform and audit\" \/>\n<meta property=\"og:description\" content=\"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/\" \/>\n<meta property=\"og:site_name\" content=\"Hoja Mustaffa Abdul Latheef \u2013 Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-02T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:site\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/\"},\"author\":{\"name\":\"Hoja Mustaffa Abdul Latheef\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"headline\":\"Composer for TYPO3 projects: path repos, platform and audit\",\"datePublished\":\"2026-11-02T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/\"},\"wordCount\":875,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg\",\"keywords\":[\"Composer\",\"DevOps\",\"Security\",\"TYPO3\"],\"articleSection\":[\"DevOps &amp; tooling\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/\",\"name\":\"Composer for TYPO3: path repos, platform and audit\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg\",\"datePublished\":\"2026-11-02T07:00:00+00:00\",\"description\":\"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg\",\"contentUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg\",\"width\":1200,\"height\":630,\"caption\":\"Composer setup that ages well\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/composer-for-typo3-projects-path-repos-platform-and-audit\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Composer for TYPO3 projects: path repos, platform and audit\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\",\"name\":\"Hoja Mustaffa Abdul Latheef \u2013 Blog\",\"description\":\"Notes from daily work with TYPO3, PHP and AI-assisted engineering\",\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hoja.in\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\",\"name\":\"Hoja Mustaffa Abdul Latheef\",\"logo\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/image\\\/\"},\"description\":\"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.\",\"sameAs\":[\"https:\\\/\\\/hoja.in\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Composer for TYPO3: path repos, platform and audit","description":"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/","og_locale":"en_US","og_type":"article","og_title":"Composer for TYPO3: path repos, platform and audit","og_description":"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.","og_url":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/","og_site_name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","article_published_time":"2026-11-02T07:00:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg","type":"image\/jpeg"}],"author":"Hoja Mustaffa Abdul Latheef","twitter_card":"summary_large_image","twitter_creator":"@hojaonline","twitter_site":"@hojaonline","twitter_misc":{"Written by":"Hoja Mustaffa Abdul Latheef","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#article","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/"},"author":{"name":"Hoja Mustaffa Abdul Latheef","@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"headline":"Composer for TYPO3 projects: path repos, platform and audit","datePublished":"2026-11-02T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/"},"wordCount":875,"commentCount":0,"publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"image":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg","keywords":["Composer","DevOps","Security","TYPO3"],"articleSection":["DevOps &amp; tooling"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/","url":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/","name":"Composer for TYPO3: path repos, platform and audit","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#primaryimage"},"image":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg","datePublished":"2026-11-02T07:00:00+00:00","description":"A TYPO3 Composer project with a path repository for local extensions, config.platform.php for production PHP, composer audit in CI and abandoned packages.","breadcrumb":{"@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#primaryimage","url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg","contentUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/composer-for-typo3-projects-path-repos-platform-and-audit.jpg","width":1200,"height":630,"caption":"Composer setup that ages well"},{"@type":"BreadcrumbList","@id":"https:\/\/hoja.in\/blog\/composer-for-typo3-projects-path-repos-platform-and-audit\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hoja.in\/blog\/"},{"@type":"ListItem","position":2,"name":"Composer for TYPO3 projects: path repos, platform and audit"}]},{"@type":"WebSite","@id":"https:\/\/hoja.in\/blog\/#website","url":"https:\/\/hoja.in\/blog\/","name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","description":"Notes from daily work with TYPO3, PHP and AI-assisted engineering","publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hoja.in\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b","name":"Hoja Mustaffa Abdul Latheef","logo":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/image\/"},"description":"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.","sameAs":["https:\/\/hoja.in\/"]}]}},"_links":{"self":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/110","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/comments?post=110"}],"version-history":[{"count":1,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions"}],"predecessor-version":[{"id":178,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/110\/revisions\/178"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media\/111"}],"wp:attachment":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media?parent=110"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/categories?post=110"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/tags?post=110"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}