---
title: "Configuration"
manual: "Frontend Theme for Extension Development"
version: "main"
source: "Configuration/Index.rst"
modified: "2026-09-17T04:52:50+00:00"
---

# Configuration

## Enabling the theme for a site

The theme ships a **site set**. A site enables it by depending on that set in
its `config/sites/<identifier>/config.yaml`:

```yaml
dependencies:
  - sbuerk/theme-extension-development
```

Nothing else is required. The set brings the TypoScript, the page rendering and
the stylesheet with it, and no **sys_template** record is needed. The
set itself declares neither dependencies nor settings — everything an
integrator changes is a TypoScript constant, and those are described below.

In the backend the same set can be selected under
**Site Management > Sites** in the **Sets** field of the site.

## Installations without site sets

For an installation that does not use site sets, the theme additionally
registers a classic static template. Create a **sys_template** record on
the root page and include **Theme Extension Development** in
**Include static (from extensions)**.

Both paths read the same TypoScript files, so what they deliver is identical.

> [!NOTE]
> Use one mechanism or the other. When a site depends on the set, the static
> include deactivates itself — its constants and setup are wrapped in a
> condition asking whether the set is active for the current site, so an
> installation that has both configured is not served the theme twice.
>
> That condition asks the site for the sets it declares **itself**. A site
> that pulls the theme in transitively, by depending on another set which in
> turn depends on this one, is not covered: there the static include has to
> stay out of the **sys_template** record.

## Templates and stylesheet

The Fluid paths and the stylesheet are TypoScript constants, so an integrator
can render their own templates without editing the theme:

| Constant | Default |
| --- | --- |
| `theme.templateRootPath` | `EXT:theme_extension_development/Resources/Private/Templates/` |
| `theme.partialRootPath` | `EXT:theme_extension_development/Resources/Private/Partials/` |
| `theme.layoutRootPath` | `EXT:theme_extension_development/Resources/Private/Layouts/` |
| `theme.stylesheet` | `EXT:theme_extension_development/Resources/Public/Css/theme.css` |

```typoscript
theme {
    templateRootPath = EXT:my_site_package/Resources/Private/Templates/
    partialRootPath = EXT:my_site_package/Resources/Private/Partials/
    layoutRootPath = EXT:my_site_package/Resources/Private/Layouts/
    stylesheet = EXT:my_site_package/Resources/Public/Css/my-theme.css
}
```

The three paths are those of both content element objects:
`lib.contentElement`, which renders the classic content elements,
and `lib.themeContentElement`, which renders the theme's own - see
[Important: Theme content elements have their own frame](../Changelog/2.0/Important-ThemeContentElementObject.html#important-theme-content-element-object). A root path added to one of the
two objects directly reaches only the elements of that object.

The stylesheet is compiled from SCSS sources that ship with the extension, so
it can also be rebuilt with different design tokens instead of being replaced —
see [Feature: Design tokens, with light and dark appearance](../Changelog/2.0/Feature-DesignTokens.html#feature-design-tokens).

## Image width

The image based elements scale their images to the width the layout gives the
content column. That width is a constant, because nothing in TypoScript can
read it out of the stylesheet:

```typoscript
theme.media {
    # The width in pixels the gallery is computed for.
    maxGalleryWidth = 1200

    # The same, for an element positioned beside the text.
    maxGalleryWidthInText = 420
}
```

The default matches the `75rem` of `--theme-content-max-width`. Set it too
low and images are processed smaller than they are displayed, which shows. Set
it far too high and every image is processed at a size no visitor ever sees.

## Appearance and palette

The theme renders in a light and a dark appearance and carries five colour
palettes. What is rendered server side — before the display settings in the
header can restore a visitor's choice from `localStorage` — is configured
with three constants:

| Constant | Default | Values |
| --- | --- | --- |
| `theme.appearance.default` | `auto` | `auto`, `light`, `dark` |
| `theme.appearance.palette` | `neutral` | `neutral`, `ember`, `ocean`, `moss`, `violet` |
| `theme.appearance.contentOutline` | `on` | `on`, `off` |

They are written onto the `<html>` tag as `data-theme`, `data-palette`
and `data-theme-content-outline`. Two of those are worth knowing exactly:

-   `auto` renders **no** `data-theme` attribute at all. The appearance is
    then left to the operating system through `color-scheme`, which is what
    `light-dark()` in the stylesheet resolves against. A palette has no such
    case, so `neutral` is still written out.
-   `contentOutline` draws the labelled outline around every content element.
    Only `off` has a rule of its own; `on` is simply the absence of it. It
    is a development and staging affordance — a site package rendering for real
    visitors sets it to `off`.

All three are defaults. A visitor can change each of them behind the cog at
the end of the header - the outline with the **Element outlines**
switch - and the choice is kept in that browser. **Reset** in the same
panel returns to the values configured here: they are also handed to the page
template as `settings.appearance.default`, `settings.appearance.palette`
and `settings.appearance.contentOutline`, and rendered next to the control
for exactly that purpose.

See [Feature: Display settings behind a cog button](../Changelog/2.0/Feature-DisplaySettings.html#feature-display-settings) for the display settings,
[Feature: Appearance switcher](../Changelog/2.0/Feature-AppearanceSwitcher.html#feature-appearance-switcher) for the mechanism behind them and
[Feature: Design tokens, with light and dark appearance](../Changelog/2.0/Feature-DesignTokens.html#feature-design-tokens) for what the palettes are built from.

## Backend layouts and page templates

The theme ships six backend layouts through page TSconfig, and the layout an
editor selects picks the Fluid template the page is rendered with:

| Identifier | Backend label | Columns (`colPos`) | Page template |
| --- | --- | --- | --- |
| `default` | **Default** | main (0) | `Page/Default.html` |
| `content` | **Content page** | stage (2), main (0), footer 1-4 (11-14), footer meta (10) | `Page/Content.html` |
| `content_sidebar` | **Content page with sidebar** | stage (2), main (0), sidebar (1), footer 1-4 (11-14), footer meta (10) | `Page/ContentSidebar.html` |
| `start` | **Start page** | stage (2), main (0), footer 1-4 (11-14), footer meta (10) | `Page/Start.html` |
| `styleguide` | **Styleguide** | unused (999) | `Page/Styleguide.html` |
| `forms` | **Form showcase** | unused (999) | `Page/Forms.html` |

The `colPos` numbers are a contract, not an implementation detail: the same
number means the same slot in every layout, which is what lets an editor change
a page's layout without content disappearing. The footer columns and the footer
meta row slide down the rootline, so they are edited once on the start page and
appear on every page below it.

The mapping is by convention rather than by configuration: the identifier is
upper-camel-cased and prefixed with `Page/`, so a new layout needs a
TSconfig file and a template of the matching name and nothing else. A page
without a layout, and a page whose layout is TYPO3's built-in
**\[None\]**, both render with `Page/Default.html`.

See [Feature: Backend layouts decide the page template](../Changelog/2.0/Feature-BackendLayouts.html#feature-backend-layouts).

## Content elements

The theme brings its own content element rendering and does **not** depend on
`fluid_styled_content` — that extension is not required here. An
installation that has it anyway enables the bridge set instead, see
[Feature: A bridge to fluid_styled_content](../Changelog/2.0/Feature-FluidStyledContentBridge.html#feature-fluid-styled-content-bridge). What the theme's own rendering
covers:

-   Every classic content element `EXT:frontend` registers, including
    **Text & Media**, **Bullet List**, **Table**,
    **File Links**, **Insert Records**, **Divider** and
    **Plain HTML** — see [Feature: Core content elements](../Changelog/2.0/Feature-CoreContentElements.html#feature-core-content-elements).
-   All eleven menu elements — see [Feature: Menu content elements](../Changelog/2.0/Feature-MenuContentElements.html#feature-menu-content-elements) —
    and cards and thumbnails for two of them — see
    [Feature: Cards and thumbnails for page menus](../Changelog/2.0/Feature-MenuCardLayouts.html#feature-menu-card-layouts).
-   The content elements of the theme's own, in a **Theme** group —
    see [Feature: Theme content elements](../Changelog/2.0/Feature-ThemeContentElements.html#feature-theme-content-elements),
    [Feature: Notice, tabs and accordion elements](../Changelog/2.0/Feature-NoticeTabsAccordionElements.html#feature-notice-tabs-accordion-elements),
    [Feature: Icon content elements](../Changelog/2.0/Feature-IconContentElements.html#feature-icon-content-elements),
    [Feature: Card group, timeline and teaser list](../Changelog/2.0/Feature-CardGroupTimelineTeaserList.html#feature-card-group-timeline-teaser-list),
    [Feature: Carousel and split tiles](../Changelog/2.0/Feature-CarouselAndSplitTiles.html#feature-carousel-and-split-tiles),
    [Feature: External media, without loading it in advance](../Changelog/2.0/Feature-ExternalMedia.html#feature-external-media) and
    [Feature: Pricing plans](../Changelog/2.0/Feature-PricingElement.html#feature-pricing-element).
-   A wall layout for the card group — see [Feature: A wall layout for the card group](../Changelog/2.0/Feature-CardWall.html#feature-card-wall).
-   **Enlarge on click**, which opens a lightbox — see
    [Feature: Enlarge on click opens a lightbox](../Changelog/2.0/Feature-GalleryLightbox.html#feature-gallery-lightbox).
-   Audio and video files in **Text & Media**, with a caption track —
    see [Feature: Audio and video in Text & Media](../Changelog/2.0/Feature-AudioAndVideoInTextMedia.html#feature-audio-and-video).
-   A language menu in the site header, which shows a language the current page
    is not translated into as unavailable rather than hiding it — see
    [Feature: Language menu](../Changelog/2.0/Feature-LanguageMenu.html#feature-language-menu).
-   A table of contents in the sidebar and a **Back to top** link, both
    from the fields of the **Appearance** tab — see
    [Feature: Table of contents, and a link to the top](../Changelog/2.0/Feature-TableOfContentsAndLinkToTop.html#feature-table-of-contents-and-link-to-top).
-   Third-party Extbase plugins, which render through a generic template
    without any per-plugin configuration — see
    [Feature: Extbase plugin rendering](../Changelog/2.0/Feature-ExtbasePluginRendering.html#feature-extbase-plugin-rendering) — on both delivery paths, the
    site set and the static include.

The fields of the **Appearance** tab - frame, space before and after -
and the alignment and style of the header change how an element looks, and the
page TSconfig of the theme takes the ones it does not render out of the form -
see [Feature: Appearance fields of content elements](../Changelog/2.0/Feature-ContentElementAppearance.html#feature-content-element-appearance).

Nothing an editor can create is left without a rendering definition, and a test
asserts exactly that: it walks the content types registered in TCA and fails if
the core's "no rendering definition" notice appears for any of them.

## Links

The link of a theme content element has a style and an optional icon - see
[Feature: An icon and a style for a theme link](../Changelog/2.0/Feature-ThemeLinkIconAndStyle.html#feature-theme-link-icon-and-style). The icon fields offer about a
hundred icons by default; page TSconfig widens the list - see
[Feature: Editors pick an icon by name](../Changelog/2.0/Feature-IconPicker.html#feature-icon-picker).

A link to another site, a file, an email address or a phone number is marked
with a glyph after its text, and a new window or a download is announced to
screen readers - see [Feature: External, download, mail and tel links](../Changelog/2.0/Feature-LinkDecoration.html#feature-link-decoration). A constant switches that
off:

```typoscript
theme.linkDecoration = 0
```

## Demo content

A page tree to look at is imported rather than built by hand. The extension
ships it as a seed set of
[sbuerk/data-factory](https://packagist.org/packages/sbuerk/data-factory),
which is suggested rather than required:

```bash
composer require --dev sbuerk/data-factory
vendor/bin/typo3 data-factory:import theme-demo
```

The set seeds a start page, pages for typography and media, one page
deliberately without a backend layout, a `/elements` branch carrying every
content type, and a `/styleguide` page rendering the whole component library
— see [Feature: A seeded showcase of every element](../Changelog/2.0/Feature-SeededShowcaseTree.html#feature-seeded-showcase-tree) and [Feature: A styleguide page](../Changelog/2.0/Feature-Styleguide.html#feature-styleguide). Its
records declare their uids and point at each other by them, so it is imported
into an installation where those uids are free. The set declares no site
configuration: create one with root page `1` afterwards, which is also what
makes the tree answer in the frontend. `data-factory:import --help` lists
every option.
