Modern TYPO3 development combines PAGEVIEW's streamlined rendering with Site Sets' configuration power. Build maintainable site packages that scale across multiple sites effortlessly.
TYPO3 v13 changed how we think about site packages. PAGEVIEW simplified page rendering while Site Sets revolutionized configuration management. But how do you combine them effectively?
Let's build a real site package that uses both features properly.
Before v13, site packages meant complex TypoScript configurations and scattered template files. Site configuration lived in YAML files that were hard to share between projects.
PAGEVIEW removes most TypoScript complexity. Site Sets make configurations portable and reusable. Together, they create cleaner, more maintainable code.
Setting Up Your Site Package Structure
Create your extension structure first:
my_site_package/
├── Configuration/
│ ├── Sets/
│ │ └── MyTheme/
│ │ ├── config.yaml
│ │ ├── page.tsconfig
│ │ └── setup.typoscript
│ ├── TCA/
│ └── TypoScript/
├── Resources/
│ ├── Private/
│ │ ├── Templates/
│ │ │ └── Page/
│ │ ├── Partials/
│ │ └── Layouts/
│ └── Public/
│ ├── Css/
│ ├── JavaScript/
│ └── Images/
└── ext_emconf.php
Creating Your First Site Set
Site Sets replace the old static template approach. Create Configuration/Sets/MyTheme/config.yaml:
name: my-theme
label: My Corporate Theme
dependencies:
- typo3/fluid-styled-content
- typo3/seo
settings:
website:
logo: EXT:my_site_package/Resources/Public/Images/logo.svg
colors:
primary: '#0066cc'
secondary: '#f8f9fa'
The dependencies automatically load required functionality. No more hunting through static templates.
PAGEVIEW Template Setup
PAGEVIEW uses a simple template approach. Create your page template at Resources/Private/Templates/Page/Default.html:
<html lang="{site.language.twoLetterIsoCode}" data-namespace-typo3-fluid="true">
<f:layout name="Default" />
<f:section name="Main">
<div class="container">
<header class="site-header">
<f:image src="{settings.website.logo}" alt="{site.websiteTitle}" class="logo" />
<f:cObject typoscriptObjectPath="lib.navigation" />
</header>
<main class="content">
<h1>{page.title}</h1>
<f:cObject typoscriptObjectPath="lib.content.main" />
</main>
</div>
</f:section>
</html>
Notice how we access Site Set settings directly with {settings.website.logo}. Much cleaner than old TypoScript constants.
Minimal TypoScript Configuration
With PAGEVIEW, your TypoScript becomes minimal. Create Configuration/Sets/MyTheme/setup.typoscript:
# Page object - PAGEVIEW handles most rendering
page = PAGE
page {
typeNum = 0
# PAGEVIEW template
10 = PAGEVIEW
10 {
templateRootPaths.10 = EXT:my_site_package/Resources/Private/Templates/
partialRootPaths.10 = EXT:my_site_package/Resources/Private/Partials/
layoutRootPaths.10 = EXT:my_site_package/Resources/Private/Layouts/
variables {
content < styles.content.get
}
}
# CSS and JS
includeCSS.theme = EXT:my_site_package/Resources/Public/Css/theme.css
includeJS.theme = EXT:my_site_package/Resources/Public/JavaScript/theme.js
}
# Simple navigation
lib.navigation = HMENU
lib.navigation {
1 = TMENU
1.NO.linkWrap = <li>|</li>
1.ACT = 1
1.ACT.linkWrap = <li class="active">|</li>
wrap = <ul class="nav">|</ul>
}
# Content rendering
lib.content.main < styles.content.get
That's it. No complex rendering definitions or content object configurations.
Page TSconfig in Site Sets
Add page-specific configuration to Configuration/Sets/MyTheme/page.tsconfig:
# Backend layout
mod.web_layout.BackendLayouts {
default {
title = Default Layout
icon = EXT:my_site_package/Resources/Public/Images/backend_layout.svg
config {
backend_layout {
colCount = 1
rowCount = 2
rows {
1 {
columns.1 {
name = Header
colPos = 1
}
}
2 {
columns.1 {
name = Main Content
colPos = 0
}
}
}
}
}
}
}
# Content element restrictions
TCEFORM.tt_content {
CType.removeItems = div,html
layout.altLabels {
1 = Highlighted
2 = Boxed Content
}
}
Site Configuration Integration
Create your site configuration at config/sites/main/config.yaml and reference your Site Set:
rootPageId: 1
base: 'https://example.com/'
languages:
-
title: English
enabled: true
languageId: 0
base: /
typo3Language: default
locale: en_US.UTF-8
iso-639-1: en
navigationTitle: English
hreflang: en-US
flag: us
dependencies:
- my-theme
settings:
website:
contactEmail: info@example.com
socialMedia:
twitter: '@example'
linkedin: 'company/example'
Site-specific settings override Site Set defaults. This makes the same Site Set work across different projects.
Multi-Site Setup Benefits
Here's where Site Sets really shine. Need the same design for multiple clients? Just create different site configurations:
Client A: config/sites/client-a/config.yaml
rootPageId: 10
base: 'https://client-a.com/'
dependencies:
- my-theme
settings:
website:
logo: EXT:my_site_package/Resources/Public/Images/client-a-logo.svg
colors:
primary: '#ff6600'
Client B: config/sites/client-b/config.yaml
rootPageId: 20
base: 'https://client-b.com/'
dependencies:
- my-theme
settings:
website:
logo: EXT:my_site_package/Resources/Public/Images/client-b-logo.svg
colors:
primary: '#009900'
Same Site Set, different branding. No code duplication.
Advanced PAGEVIEW Features
PAGEVIEW supports data processors just like FLUIDTEMPLATE. Add complex data preparation:
page.10 {
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
10 {
levels = 2
as = mainNavigation
}
20 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
20 {
table = tt_news
pidInList = 15
orderBy = datetime DESC
max = 3
as = latestNews
}
}
}
Use the processed data in your template:
<nav class="main-nav">
<f:for each="{mainNavigation}" as="item">
<f:link.page pageUid="{item.data.uid}" class="{f:if(condition: item.active, then: 'active')}">{item.title}</f:link.page>
</f:for>
</nav>
<aside class="news-sidebar">
<h3>Latest News</h3>
<f:for each="{latestNews}" as="article">
<article>
<h4>{article.title}</h4>
<time datetime="{article.datetime -> f:format.date(format: 'Y-m-d')}">{article.datetime -> f:format.date()}</time>
</article>
</f:for>
</aside>
Debugging and Development Tips
Enable debug output during development. Add this to your Site Set's TypoScript:
[applicationContext == "Development"]
config.debug = 1
page.10.settings.debugMode = 1
[END]
Use the TYPO3 admin panel to inspect PAGEVIEW rendering. Go to Admin Panel > Info and check “Display cObject times and SQL queries.”
Common Migration Pitfalls
Don't mix old and new approaches. Remove lib.parseFunc_RTE references when using PAGEVIEW. The new system handles RTE parsing automatically.
Site Set dependencies matter. List them in the right order. Core sets should come before custom ones:
dependencies:
- typo3/fluid-styled-content # Core first
- typo3/seo # Core features
- my-theme # Custom last
Settings cascade properly. Site configuration overrides Site Set settings, which override extension defaults. Use this hierarchy intentionally.
Performance Considerations
PAGEVIEW renders faster than traditional FLUIDTEMPLATE approaches. But don't add unnecessary data processors. Each processor runs on every page load.
Cache your complex calculations:
lib.expensiveCalculation = USER
lib.expensiveCalculation {
userFunc = MyVendor\MyExtension\UserFunc\Calculator->process
cache.lifetime = 3600
cache.tags = pages
}
Site Sets don't impact frontend performance. They're processed during bootstrap, not on each request.
Testing Your Site Package
Create a simple test to verify your Site Set loads correctly:
<?php
// Tests/Functional/SiteSetTest.php
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
class SiteSetTest extends FunctionalTestCase
{
protected array $testExtensionsToLoad = [
'my_site_package'
];
public function testSiteSetIsLoadable(): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/pages.csv');
$this->setUpFrontendSite(1, [
'dependencies' => ['my-theme']
]);
$response = $this->executeFrontendSubRequest(
new InternalRequest('https://example.com/')
);
$this->assertEquals(200, $response->getStatusCode());
$this->assertStringContainsString('<title>', (string)$response->getBody());
}
}
What's Next?
You now have a modern TYPO3 site package that uses both PAGEVIEW and Site Sets effectively. The combination creates cleaner code that's easier to maintain and deploy across multiple sites.
Consider adding:
- Custom content elements using the new registration API
- Advanced data processors for complex content scenarios
- Asset building integration with Vite or Webpack
- Automated deployment workflows that handle Site Set configurations
The v13 approach scales better than previous methods. Start with this foundation and add complexity only when needed.
FAQ
No, PAGEVIEW is exclusive to TYPO3 v13 and later. For older versions, stick with FLUIDTEMPLATE.
No, but they reduce TypoScript complexity significantly. You still need TypoScript for page objects and lib definitions.
Create a Site Set configuration, move constants to settings, and update your site configuration to reference the new Site Set.
Yes, list multiple dependencies in your site configuration. They're processed in order.
Yes, Site Set configurations are cached during bootstrap. Clear system cache when changing config.yaml files.
Minimal changes required. PAGEVIEW uses the same Fluid syntax as FLUIDTEMPLATE.
Post a Comment