---
title: "Fluid Templates from Scratch"
manual: "Site Package Tutorial"
version: "13.4"
permalink: "https://docs.typo3.org/permalink/t3sitepackage:fluid-templates-scratch@13.4"
source: "FluidTemplates/FromTheScratch.rst"
rendered: "2026-09-24T15:39:33+00:00"
---

# Fluid Templates from Scratch {#fluid-templates-scratch}

-   [Create the Fluid templates](https://docs.typo3.org/permalink/t3sitepackage:create-the-fluid-templates@13.4)
-   [The Fluid template for the subpage](https://docs.typo3.org/permalink/t3sitepackage:the-fluid-template-for-the-subpage@13.4)
-   [Extract the repeated part to a layout](https://docs.typo3.org/permalink/t3sitepackage:extract-the-repeated-part-to-a-layout@13.4)

## Create the Fluid templates {#create-template}

Copy the main [static HTML file](https://docs.typo3.org/permalink/t3sitepackage:theme-example-static-html@13.4) from
`Resources/Public/StaticTemplate/default.html`
to `Resources/Private/PageView/Pages/Default.html`. You can override
the file created in step [Minimal site package - The TYPO3 Fluid
version](https://docs.typo3.org/permalink/t3sitepackage:minimal-extension-fluid@13.4). The file name must begin
with a capital letter

The template name `Default.html` is used as a fall back if no other template
names are defined. Do not change it for now.

Even though this file ends on `.html` it will be interpreted by the templating
engine Fluid.

TYPO3 takes care of creating the outermost HTML structure of the site, including
the `<html>` and `<head>` tags therefore they need to be removed from the
template:

**Resources/Private/PageView/Pages/Default.html (difference)**

```diff
-<!doctype html>
-<html lang="en" data-bs-theme="auto">
-<head>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <title>TYPO3 site package example</title>
-    <link href="../Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" rel="stylesheet">
-    <link href="../Css/main.css" rel="stylesheet">
-</head>
-<body>
 <main>
     ...
 </main>
-<script src="../Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js"></script>
-<script src="../JavaScript/main.js"></script>
-</body>
-</html>

```

The Fluid template `Default.html` now contains only the HTML
code inside the body:

**Resources/Private/PageView/Pages/Default.html**

```html
<main>
    <nav class="navbar navbar-expand-lg bg-body-tertiary mb-4">
        <div class="container">
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#menuToggler"
                    aria-controls="menuToggler" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="menuToggler">
                <a href="#" class="navbar-brand">
                    <img src="../Images/logo.svg" alt="Logo" height="50px" class="pe-3">
                    Site name
                </a>

                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">Features</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">FAQs</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">About</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container">
        <div class="p-5 mb-4 bg-body-tertiary">
            <div class="container-fluid py-5">
                <h1 class="display-5 fw-bold">Custom stage</h1>
                <p class="col-md-8 fs-4">This stage contains a button to demonstrate that JavaScript is working: </p>
                <button class="btn btn-dark btn-lg" role="button" href="#" id="exampleButton">Example button</button>
            </div>
        </div>
    </div>
    <div class="container">
        <h2>Start page content</h2>
        <p>The content of the start page is displayed here. This content should be generated from the content element of the startpage </p>
    </div>
    <div class="container">
        <footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
            <div class="col-md-4 d-flex align-items-center">
                <a href="#" class="mb-3 me-2 mb-md-0 text-body-secondary text-decoration-none lh-1">
                    <img src="../Images/logo.svg" alt="Logo" height="24" class="bi">
                </a>
                <span class="mb-3 mb-md-0 text-body-secondary">&copy; 2024 Site name</span>
            </div>

            <ul class="nav col-md-4 justify-content-end">
                <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Data privacy</a></li>
                <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Imprint</a></li>
            </ul>
        </footer>
    </div>
</main>
```

Flush the caches and preview the page. You should now see a pure HTML page
without any styles or images. We will add them in a further step.

> [!NOTE]
> Each time you change a Fluid template you must flush the caches. Fluid
> templates preprocessed into PHP files and stored in the folder
> `var/cache/code/fluid_template`.

### Load assets (CSS, JavaScript) {#assets}

Load all CSS which had been removed in step
[Create the Fluid templates](https://docs.typo3.org/permalink/t3sitepackage:create-template@13.4)
using the [Asset.css ViewHelper \<f:asset.css>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Asset/Css.html#typo3-fluid-asset-css).

Replace `<script>` tags in the body by using the
[Asset.script ViewHelper \<f:asset.script>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Asset/Script.html#typo3-fluid-asset-script).

**Resources/Private/PageView/Pages/Default.html (difference)**

```diff
+ <f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
+ <f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
  <main>
      ...
  </main>
- <script src="../Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js"></script>
- <script src="../JavaScript/main.js"></script>
+ <f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
+ <f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />

```

The path to the assets will be resolved by TYPO3. `EXT:` tells TYPO3 that this is
an extension path. `my_site_package` is the
[Extension name defined in the composer.json](https://docs.typo3.org/permalink/t3sitepackage:extension-configuration-composer@13.4).

Flush all caches and preview the page.
..  todo: Link to cache and preview pages in getting started once they exist

When you load your page and inspect it with the developer tools of your browser
you will notice that the assets are loaded from paths like
`/_assets/99a57ea771f379715c522bf185e9a315/Css/main.css?1728057333`. You must
never try to use these path directly, for example as absolute paths. They can
change at any time. Only use the `EXT:` syntax.

When you now preview the page you will notice that the your page is loaded
with the dummy content from the template and functioning CSS and JavaScript.
The logo however is not found.

### Load images in Fluid {#images}

Replace all `<img>` tags in the template with the
[Image ViewHelper \<f:image>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Image.html#typo3-fluid-image):

**Resources/Private/PageView/Pages/Default.html (difference)**

```diff
-<img src="../Images/logo.svg" alt="Logo" height="50px" class="pe-3">
+<f:image src="EXT:site_package/Resources/Public/Images/logo.svg" alt="Logo" class="pe-3" />

```

Just like happened with the CSS paths in step
[Load assets (CSS, JavaScript)](https://docs.typo3.org/permalink/t3sitepackage:assets@13.4) the path to the
image is now replaced in the output by a path like
`/_assets/99a57ea771f379715c522bf185e9a315/Images/logo.svg?1728057333`.

### Split up the template into partials {#partials}

If you compare the two static templates
`Resources/Public/StaticTemplate/default.html`
and `Resources/Public/StaticTemplate/subpagepage.html` they share many
parts like the footer or the header with the menu. In order to reuse those parts
we extract them to their own Fluid files. These are called partials and stored
in path `Resources/Private/PageView/Partials`.

We can use the [Render ViewHelper \<f:render>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Render.html#typo3-fluid-render)
to render the partial in the correct place.

Remove the header from the template and replace it with a render ViewHelper:

**Resources/Private/PageView/Pages/Default.html (difference)**

```diff
 <main>
     <nav class="navbar navbar-expand-lg bg-body-tertiary mb-4">
-        <div class="container">
-            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#menuToggler"
-                    aria-controls="menuToggler" aria-expanded="false" aria-label="Toggle navigation">
-                <span class="navbar-toggler-icon"></span>
-            </button>
-            <div class="collapse navbar-collapse" id="menuToggler">
-                <a href="#" class="navbar-brand">
-                    <img src="../Images/logo.svg" alt="Logo" height="50px" class="pe-3">
-                    Site name
-                </a>
-
-                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-                    <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
-                    <li class="nav-item"><a href="#" class="nav-link">Features</a></li>
-                    <li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
-                    <li class="nav-item"><a href="#" class="nav-link">FAQs</a></li>
-                    <li class="nav-item"><a href="#" class="nav-link">About</a></li>
-                </ul>
-            </div>
-        </div>
-    </nav>
+    <f:render partial="Header" arguments="{_all}"/>
     ...
 </main>

```

Move the Fluid code you just remove to a file called
`my-site-package/Resources/Private/PageView/Partials/Header.html`.

Do the same with the stage, the breadcrumb, and the footer.

You should now have the following files:

-   packages/my_site_package/Resources/Private/PageView
    -   Pages
        -   Default.html
        -   Subpage.html
    -   Partials
        -   Footer.html
        -   Header.html
        -   Stage.html

The Fluid template `Resources/Private/PageView/Pages/Default.html`
should now look like this:

**Resources/Private/PageView/Pages/Default.html**

```html
<f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
<f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
<main>
    <f:render partial="Header" arguments="{_all}"/>
    <f:render partial="Stage" arguments="{records: content.stage.records}"/>
    <div class="container">
        <h2>Start page content</h2>
        <p>The content of the start page is displayed here. This content should be generated from the content element of the startpage </p>
    </div>
    <f:render partial="Footer" arguments="{_all}"/>
</main>
<f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
<f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />

```

You will learn how to display the dynamic content in chapter
[Display the content elements on your page](https://docs.typo3.org/permalink/t3sitepackage:content-mapping@13.4).

### Extract the menu into a partial {#create-partial-header}

Partials can also be rendered from within another partial. We move the menu in
the partial `Resources/Private/PageView/Partials/Header.html` to its
own partial, `Resources/Private/PageView/Partials/Navigation/Menu.html`:

**packages/my_site_package/Resources/Private/PageView/Partials/Header.html (Difference)**

```diff
 <nav class="navbar navbar-expand-lg bg-body-tertiary mb-4">
     <div class="container">
         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#menuToggler"
                 aria-controls="menuToggler" aria-expanded="false" aria-label="Toggle navigation">
             <span class="navbar-toggler-icon"></span>
         </button>
         <div class="collapse navbar-collapse" id="menuToggler">
             <a href="#" class="navbar-brand">
                 <f:image src="{settings.mySitepackage.logo}" alt="{settings.mySitepackage.logo-alt}" class="pe-3" />
                 Site name
             </a>
-            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-                <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
-                <li class="nav-item"><a href="#" class="nav-link">Features</a></li>
-                <li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
-                <li class="nav-item"><a href="#" class="nav-link">FAQs</a></li>
-                <li class="nav-item"><a href="#" class="nav-link">About</a></li>
-            </ul>
             <f:render partial="Navigation/Menu.html" arguments="{_all}"/>
         </div>
     </div>
 </nav>

```

The [Render ViewHelper \<f:render>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Render.html#typo3-fluid-render) is used
the same like from within the template.

Chapter [Main menu](https://docs.typo3.org/permalink/t3sitepackage:main-menu-creation@13.4) will teach you how
to make the menu work.

### Extract the footer menu into a partial {#create-partial-footer-menu}

We can also move the footer menu from
the partial `Resources/Private/PageView/Partials/Footer.html` to its
own partial, `Resources/Private/PageView/Partials/Navigation/FooterMenu.html`:

**packages/my_site_package/Resources/Private/PageView/Partials/Footer.html (Difference)**

```diff
<div class="container">
    <footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
        <div class="col-md-4 d-flex align-items-center">
            <a href="#" class="mb-3 me-2 mb-md-0 text-body-secondary text-decoration-none lh-1">
                <f:image src="EXT:my_site_package/Resources/Public/Images/logo.svg" alt="Logo" class="bi"/>
            </a>
            <span class="mb-3 mb-md-0 text-body-secondary">&copy; 2024 Site name</span>
        </div>

-        <ul class="nav col-md-4 justify-content-end">
-            <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Data privacy</a></li>
-            <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Imprint</a></li>
-        </ul>
+        <f:render partial="Navigation/FooterMenu.html" arguments="{_all}"/>
    </footer>
</div>
```

The footer menu partial looks like this:

**Resources/Private/PageView/Partials/Navigation/FooterMenu.html**

```html
<ul class="nav col-md-4 justify-content-end">
    <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Data privacy</a></li>
    <li class="nav-item"><a href="#" class="nav-link px-2 text-body-secondary">Imprint</a></li>
</ul>
```

### Move the content into a section {#create-section}

You can also move a part of the template into a section, surrounded by a
[Section ViewHelper \<f:section>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Section.html#typo3fluid-fluid-section)
and use the [Render ViewHelper \<f:render>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Render.html#typo3-fluid-render)
with argument `section` to render it.

We move the content, including the Stage into such a section:

**Resources/Private/PageView/Pages/Default.html (difference)**

```diff
 <f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
 <f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
 <main>
     <f:render partial="Header" arguments="{_all}"/>
-    <f:render partial="Stage" arguments="{records: content.stage.records}"/>
-    <div class="container">
-        <h2>Start page content</h2>
-        <p>The content of the start page is displayed here. This content should be generated from the content element of the startpage </p>
-    </div>
+    <f:render section="Main"/>
     <f:render partial="Footer" arguments="{_all}"/>
 </main>
 <f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
 <f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />

+<f:section name="Main">
+    <f:render partial="Stage" arguments="{_all}"/>
+    <div class="container">
+        <h2>Start page content</h2>
+        <p>The content of the start page is displayed here. This content should be generated from the content element of the startpage </p>
+    </div>
+</f:section>

```

The result looks like this:

**Resources/Private/PageView/Pages/Default.html**

```html
<f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
<f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
<main>
    <f:render partial="Header" arguments="{_all}"/>
    <f:render section="Main"/>
    <f:render partial="Footer" arguments="{_all}"/>
</main>
<f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
<f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />

<f:section name="Main">
    <f:render partial="Stage" arguments="{records: content.stage.records}"/>
    <div class="container">
        <h2>Start page content</h2>
        <p>The content of the start page is displayed here. This content should be generated from the content element of the startpage </p>
    </div>
</f:section>

```

You will learn how to display the dynamic content in chapter
[Display the content elements on your page](https://docs.typo3.org/permalink/t3sitepackage:content-mapping@13.4).

## The Fluid template for the subpage {#subpage}

We can repeat the above steps for the subpage and write such a template:

**Resources/Private/PageView/Pages/Subpage.html**

```html
<f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
<f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
<main>
    <f:render partial="Header" arguments="{_all}"/>
    <f:render section="Main"/>
    <f:render partial="Footer" arguments="{_all}"/>
</main>
<f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
<f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />

<f:section name="Main">
    <f:render partial="Stage" arguments="{_all}"/>
    <f:render partial="Navigation/Breadcrumb" arguments="{_all}"/>
    <div class="container">
        <div class="row">
            <div class="col-md-8">
                <div class="h-100 p-5 text-bg-white">
                    <h2>Page content</h2>
                    <p>The content of each page can be displayed here. </p>
                </div>
            </div>
            <div class="col-md-4">
                <div class="h-100 p-5 bg-body-tertiary">
                    <h2>Sidebar </h2>
                    <p>Place for some shared content</p>
                </div>
            </div>
        </div>
    </div>
</f:section>

```

### Extract the breadcrumb into a partial {#create-partial-breadcrumb}

The subpage template contain a breadcrumb, between stage and content, that
you can also move to a partial.

The breadcrum partial looks like this:

**Resources/Private/PageView/Partials/Navigation/Breadcrumb.html**

```html
<div class="container">
    <nav aria-label="breadcrumb">
        <ol class="breadcrumb breadcrumb-chevron p-3 bg-body-tertiary">
            <li class="breadcrumb-item">
                <a class="link-body-emphasis fw-semibold text-decoration-none" href="#">Home</a>
            </li>
            <li class="breadcrumb-item">
                <a class="link-body-emphasis fw-semibold text-decoration-none" href="#">Library</a>
            </li>
            <li class="breadcrumb-item active" aria-current="page">
                Data
            </li>
        </ol>
    </nav>
</div>
```

## Extract the repeated part to a layout {#the-website-layout-file}

Lines 1-9 of file `Subpage.html` in step
[The Fluid template for the subpage](https://docs.typo3.org/permalink/t3sitepackage:subpage@13.4) are exactly the
same like in file `Resources/Private/PageView/Pages/Default.html`.

We can extract these lines into a so called Fluid layout and load them with the
[Layout ViewHelper \<f:layout>](https://docs.typo3.org/other/typo3/view-helper-reference/13.4/en-us/Global/Layout.html#typo3fluid-fluid-layout):

**Resources/Private/PageView/Pages/Subpage.html (difference)**

```diff
-<f:asset.css identifier="bootstrap" href="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
-<f:asset.css identifier="main" href="EXT:site_package/Resources/Public/Css/main.css" />
-<main>
-    <f:render partial="Header" arguments="{_all}"/>
-    <f:render section="Main"/>
-    <f:render partial="Footer" arguments="{_all}"/>
-</main>
-<f:asset.script identifier="bootstrap" src="EXT:site_package/Resources/Public/Libaries/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js" />
-<f:asset.script identifier="main" src="EXT:site_package/Resources/Public/JavaScript/main.js" />
+<f:layout name="Layout"/>
 <f:section name="Main">
     ...
 </f:section>

```

Save the extracted layout to a file called
`Resources/Private/PageView/Layouts/Layout.html`. This file now contains
the following:

**packages/my_site_package/Resources/Private/PageView/Layouts/PageLayout.html**

```html
<f:asset.css identifier="bootstrap" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
<f:asset.css identifier="main" href="EXT:my_site_package/Resources/Public/Css/main.css" />
<main>
    <f:render partial="Header" arguments="{_all}"/>
    <f:render section="Main"/>
    <f:render partial="Footer" arguments="{_all}"/>
</main>
<f:asset.script identifier="bootstrap" src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" />
<f:asset.script identifier="main" src="EXT:my_site_package/Resources/Public/JavaScript/main.js" />

```

Repeat the same for file `Resources/Private/PageView/Pages/Default.html`.

-   packages/my_site_package/Resources/Private/PageView
    -   Layouts
        -   Layout.html
    -   Pages
        -   Default.html
        -   Subpage.html
    -   Partials
        -   Navigation
            -   Breadcrumb.html
            -   FooterMenu.html
            -   Menu.html
        -   Footer.html
        -   Header.html
        -   Stage.html

You can use the [Site Package Builder](https://get.typo3.org/sitepackage) to
create a customized site package. If you want to follow this tutorial, choose
"Site Package Tutorial" as base package.
