{"id":18040536,"url":"https://github.com/richardhj/contao-theme-framework","last_synced_at":"2026-04-12T22:21:07.619Z","repository":{"id":45860069,"uuid":"346723248","full_name":"richardhj/contao-theme-framework","owner":"richardhj","description":"A new standardized and database-less way to build frontend themes in Contao.","archived":false,"fork":false,"pushed_at":"2025-02-23T20:52:30.000Z","size":123,"stargazers_count":18,"open_issues_count":1,"forks_count":0,"subscribers_count":7,"default_branch":"3.x","last_synced_at":"2025-03-23T18:54:14.706Z","etag":null,"topics":["contao","encore","twig-templates"],"latest_commit_sha":null,"homepage":"","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/richardhj.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}},"created_at":"2021-03-11T14:08:24.000Z","updated_at":"2025-02-23T20:52:34.000Z","dependencies_parsed_at":"2023-12-31T15:25:05.096Z","dependency_job_id":"35dea78a-05a7-4945-95b5-b914547e80a7","html_url":"https://github.com/richardhj/contao-theme-framework","commit_stats":{"total_commits":62,"total_committers":1,"mean_commits":62.0,"dds":0.0,"last_synced_commit":"573aaf27789d3606c843b001137f3aef08af4dad"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhj%2Fcontao-theme-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhj%2Fcontao-theme-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhj%2Fcontao-theme-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhj%2Fcontao-theme-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richardhj","download_url":"https://codeload.github.com/richardhj/contao-theme-framework/tar.gz/refs/heads/3.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248069659,"owners_count":21042680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["contao","encore","twig-templates"],"created_at":"2024-10-30T15:06:46.083Z","updated_at":"2026-04-12T22:21:02.571Z","avatar_url":"https://github.com/richardhj.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eContao Theme Framework\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eA new standardized and database-less way to build frontend themes in Contao.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/1284725/132962831-dcef78a7-2604-4782-aaf5-928321683059.png\" alt=\"\" width=\"550\"\u003e\n\u003c/p\u003e\n\n## Features\n\n- Automatically registers themes and layouts defined via a `theme.yml` manifest file: Almost no database to maintain - easier deployment!\n- Disables all redundant fields from the tl_theme and tl_layout palettes - you define all settings via the manifest file (except for the module includes).\n- Registers a themes' public folder as Asset package, supports file versioning via a `manifest.json`!\n- Out-of-the-box support for Symfony Encore and its `entrypoints.json`!\n\nThis extension is stable and supported from Contao \u003e=4.13 and will be integrated into the Contao Core at some time eventually, see https://github.com/contao/contao/issues/2781.\n\n## Installation\n\n```bash\ncomposer require richardhj/contao-theme-framework\n```\n\n## Quickstart\n\n### 1. Create a theme folder\n\nCreate a folder for your theme under `/themes` with the following structure:\n\n```text\n|- files\n|- themes\n |- my_theme\n  |- assets           (Optional folder, we recommend placing your CSS/JS files there)\n  |- public           (Distribution folder with your CSS/JS files, will be symlinked into the web/ folder)\n  |- templates        (Overridden Contao templates, for frontend modules, etc.pp.)\n  |- theme.[yml|yaml] (Theme manifest)\n```\n\nIf you do not use a preprocessor, you place all your CSS/JS files into the public folder.\n\nAlternatively, copy the boilerplate folder:\n\n```bash\ncp -r vendor/richardhj/contao-theme-framework/skeleton/theme themes/[my_theme]\n```\n\nThis command will install an opinionated starter theme pack.\n\n\u003e :information_source: Except for the directory structure that is predetermined, you are free in the technology you use (Encore, Webpack, Gulp, SASS, plain CSS, …).\n\n### 2. Write the theme manifest\n\nWrite your theme manifest:\n\n```yml\n# themes/[my_theme]/theme.yml\n\ntheme:\n  name: My cool theme\n\nlayouts:\n  # \"_default\" is a special key.\n  # Will create a \"default\" layout, and all other layouts will merge these settings.\n  # Using this key is optional.\n  # The key:value structure maps the tl_layout structure.\n  _default:\n    name: Default layout\n    template: fe_page\n    rows: 3rw\n\n  other_layout:\n    name: Other layout\n    template: fe_page_2\n\nimage_sizes:\n  # See https://docs.contao.org/dev/framework/image-processing/image-sizes/#size-configuration\n```\n\nIn a next version, the XML format for theme manifests will be available.\n\n### 3. Install themes\n\nTo install your new theme, run the migrate command:\n\n```bash\n./vendor/bin/contao-console contao:migrate -n\n```\n\n\u003e :information_source: The themes will only be updated on the migrate command when making changes on the theme manifest.\n\u003e It is best to add the migrate command to your deployment script (which is a good idea anyway).\n\nTo create the symlink for the public folder, run the following command (this only needs to be done once,\nand this is automatically done on `composer install`, so you usually should not be required to do this):\n\n```bash\n./vendor/bin/contao-console contao:symlinks\n```\n\n### 4. Create frontend modules and assign them to layouts\n\nLogin to the Contao backend, where you will find the new theme. Create frontend modules (if necessary)\nand assign them to the layouts accordingly.\n\nUsage\n-----\n\nThe following chapters describe how you write frontend code, depending on your preferred toolchain:\n\n### Vanilla (No toolchain)\n\nEach theme's public folder (i.e., `/themes/[my_theme]/public`) is registered as `assets.packages`\ncomponent. [Learn more about the Asset component.](https://symfony.com/doc/current/components/asset.html)\n\nYou can reference any file inside the theme's public folder with the `{{asset}}` insert tag\nor corresponding twig function. The theme name equals the folder name.\n\nWhen you use a `manifest.json` inside the public folder, it will be handled by Symfony's Asset\ncomponent. Make sure to use `setManifestKeyPrefix('')` in your `webpack.config.js` file then.\n\n**Example:**\n\n```html\n\u003c!-- HTML5 --\u003e\n{{asset::images/logo.svg::my_theme}}\n\n\u003c!-- Twig --\u003e\n{{ asset('images/logo.svg', 'my_theme') }}\n```\n\n\u003e :information_source: The simplest way to include a CSS file to the page is to modify the `fe_page.html5` template and include the `{{asset::css/custom.css::my_theme}}` insert tag.\n\n### Encore\n\nRead the documentation for Encore here: https://symfony.com/doc/current/frontend/encore/index.html\n\nFirst, install Webpack Encore:\n\n```shell\ncomposer require symfony/webpack-encore-bundle\n```\n\nMake sure to configure Encore properly by placing the [webpack.config.js](skeleton/theme/webpack.config.js) file inside\nyour `themes/[my_theme]/assets` folder.\n\nThen you will be able to inject your CSS and JS files to the page template:\n\n```twig\n{{ theme_link_tags('app') }}\n{{ theme_script_tags('app') }}\n```\n\n\u003e :information_source: The name \"app\" matches the name of the entry defined in the [webpack.config.js](https://github.com/richardhj/contao-theme-framework/blob/528dfb7085b0d35036ed771cb0563a6b9f3a74ac/skeleton/theme/assets/webpack.config.js#L7). You can have multiple entrypoints per theme.\n\nFinally, some tips for working with Encore and bundlers:\n\n#### Git-Ignore the public folder\n\nThe distributed theme files inside the public folder usually are versioned and contain\nduplicated information so that you do not want to check in those files to version control.\nInstead, you want to build the theme (`yarn run prod`) before deploying.\n\n\u003e :information_source: The [.gitignore file](skeleton/theme/.gitignore) of the skeleton theme may become handy.\n\n#### Use yarn workspaces to manage multiple themes\n\nYou can make use of [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/).\nThis will allow you to run the build command once when having multiple themes in use:\n\n```json\n// /package.json\n\n{\n  \"private\": true,\n  \"workspaces\": [\"themes/*/assets\"],\n  \"scripts\": {\n    \"prod\": \"yarn workspaces run prod\"\n  }\n}\n```\n\nYou then will be able to run `yarn run prod` from the root directory.\n\n### Asset Mapper\n\nRead the documentation for the Asset Mapper here: https://symfony.com/doc/current/frontend/asset_mapper.html\n\n(tba)\n\nFAQ\n---\n\n### Wait – How do I build a website if all fields are disabled from tl_layout?\n\nGood question!\n\nThe layouts in Contao are highly redundant. You don't need to configure a viewport-attribute,\nbody-class, etc. via the layout. Instead, just put those changes directly into your fe_page template.\n\nInstead of selecting CSS files and JS files via the layout (which is limited to files within /files),\ndirectly include your files via the {{asset}} insert tag or twig function (or via Encore, see below).\nDon't use the \"custom `\u003chead\u003e`\" or \"custom `\u003cscript\u003e`\" settings in your layout. It's hard to maintain and\nkeep track of. Instead, put those things directly into the template.\n\nConsidering these matters of maintainability, it's easier not to configure any settings in the layout.\nAssigning the modules to the layout sections is all you do in the layouts.\n\nIf your layouts use rows and cols, set the corresponding config in the `theme.yml`. For instance,\n`rows: 3rw` enables the header and footer section.\n\n_Using Twig templates (optional):_\n\nIn case your header and footer sections only contain static content, you do not have to configure\nthose sections in your layout. Just include those sections via Twig includes. For navigation menus,\nyou can use a Knp Menu (see below). For a user menu, you can use the [{{ app.user }} variable](https://symfony.com/doc/current/templates.html#the-app-global-variable).\nYou will be surprised how not using modules for the layout significantly enhances maintainability.\n\n### Custom layout sections\n\n[Custom layout areas](https://docs.contao.org/manual/en/layout/theme-manager/manage-page-layouts/#custom-layout-areas) in the layout work as follows.\n\nFirst, define the sections in the layout:\n\n```yaml\n# themes/[my_theme]/theme.yml\nlayouts:\n  _default:\n    name: Default layout\n    sections:\n      - title: Bereich A\n        id: custom1\n        position: manual\n        template: block_section\n      - title: Bereich B\n        id: custom2\n        position: manual\n        template: block_section\n```\n\nThen, add the section(s) to the page layout (i.e., `fe_page`):\n\n```twig\n{# themes/my_theme/fe_page.html.twig #}\n\n\u003cdiv\u003e\n  {{ section.invoke('custom1') }}\n\u003c/div\u003e\n\u003cdiv\u003e\n  {{ section.invoke('custom2') }}\n\u003c/div\u003e\n````\n\n\n```php\n\u003c!-- themes/my_theme/fe_page.html5 --\u003e\n\n\u003cdiv\u003e\n  \u003c?php $this-\u003esection('custom1') ?\u003e\n\u003c/div\u003e\n\u003cdiv\u003e\n  \u003c?php $this-\u003esection('custom2') ?\u003e\n\u003c/div\u003e\n````\n\n### Migrate to theme-framework\n\nYou can migrate your existing theme and layouts to the theme-framework.\n\nBefore running `contao:migrate`:\n\n1. Add a new column named `alias` to the `tl_theme` table and set `'alias' = 'my_theme'`\n(where `my_theme` matches the name of your theme folder).\n\n2. Add a new column named `alias` to the `tl_layout` table and set `'alias' = '_default'`\n(where `_default` matches the name of your layout defined via the manifest file).\n\n3. All layout settings defined via the manifest file will be overridden in the\n`contao:migrate` command. Existing settings won't be touched.\n\n## Best Practices\n\n### Do not rename the theme folder\n\nRenaming the theme folder will create a new Contao theme in the database internally.\nYou'll need to re-assign the layouts to the pages.\n\n### Use twig templates\n\nYou can use Twig or PHP templates by your preference. As already mentioned,\nyour templates belong to the `templates` folder.\n\nFor Twig templates, suffix your file with `.html.twig`, i.e., `fe_page.html.twig`.\nFor PHP templates, use the default naming, i.e., `fe_page.html5`.\n\nTwig templates in the theme folder use the namespace `@Contao_Theme_\u003cname\u003e`, in a way that the\ntemplate `/themes/my_theme/templates/fe_page.html.twig` can be referenced as `@Contao_Theme_MyTheme/fe_page.html.twig`.\n\n\u003e :information_source: Note that the \"theme slug\" for the Twig namespace will be transformed to CamelCase. If your theme\n\u003e folder is named `my_theme`, the Twig namespace will be `@Contao_Theme_MyTheme`.\n\nYou can place twig templates also in global (non theme-related) folders -- whatever feels right for you.\n\n| File                                           | Twig namespace and reference               | Prio (first wins) |\n|:-----------------------------------------------|:-------------------------------------------|:------------------|\n| `/themes/my_theme/templates/fe_page.html.twig` | `@Contao_Theme_MyTheme/fe_page.html.twig`  | 1                 |\n| `/templates/fe_page.html.twig`                 | `@Contao_Global/fe_page.html.twig`         | 2                 |\n| `/contao/templates/fe_page.html.twig`          | `@Contao_App/fe_page.html.twig`            | 3                 |\n\nRead more about the usage of Twig templates in Contao under \u003chttps://docs.contao.org/dev/framework/templates/twig/\u003e.\n\n### Use Webpack Encore to compile your theme assets\n\nThe skeleton theme comes with a pre-defined `webpack.config.js` file. The configuration\nwill automatically process your asset files from the `assets` folder and generate the\nbundled files into the `public` folder.\n\nWebpack Encore will also provide an `entrypoints.json` in the public folder. This helps\nto easily add the correct JS and CSS files to the current page (see above for usage).\n\n### Use a KnpMenu for navigation modules\n\nWith a KnpMenu you are much more flexible in outputting a navigation wherever you need it on the page.\n\nSee https://github.com/richardhj/contao-knp-menu for more information.\n\n### Do not deploy the assets folder\n\nThe assets folder with the source files (if present) should be excluded from the deployment\nbecause it most likely contains the node_modules folder next to the source folder.\nIn contrast, all other files, like the theme.yml manifest and public and templates folders\nneed to be uploaded when deploying.\n\n### Uninstalling\n\nYou wonder what happens to your themes when you uninstall the extension?\n\nFirst, all your themes, layouts, and image size configurations stay in Contao. They won't get removed.\n\nSecond, templates under `/themes/foobar/templates` won't use the namespace `@Contao_Theme_Foobar` anymore but the namespace `@Contao_Theme__themes_foobar_templates`. This may break your website. For this to fix, move the templates folder to `/templates/Foobar` (from the project root). The Twig namespace stays intact.\n\nThird, you lose the Encore and assets integration. This means that using the asset (`{{ asset() }}`) function or insert tag (`{{asset::*}}`) will fail. Further, the twig functions `theme_link_tags()` and `theme_script_tags()` will become unavailable. For this to fix, you have to include your CSS/JS files by directly referencing to them.\n\n### Use Symfony UX\n\n// TODO\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardhj%2Fcontao-theme-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichardhj%2Fcontao-theme-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardhj%2Fcontao-theme-framework/lists"}