---
title: Displaying Custom Entity Data on the Storefront | Shopware Community Hub
description: >-
  Learn how to display custom entity data in the storefront by configuring your
  App as a theme and using template overrides.
canonical_url: 'https://hub.shopware.com/learn/unit/app-displaying-custom-data'
---

# Displaying Custom Entity Data on the Storefront

<LearningObjectives>

- **Learn** how to **configure** an App as a **theme**.
- **Identify** and **locate** a **storefront template** with the **Symfony Profiler**.
- **Learn** how to **override** a specified **storefront template** in your App.

</LearningObjectives>

# Displaying Custom Entity Data on the Storefront

In this learning unit, we will display data from our Custom Entity on the storefront. At first, this might seem unusual – how can an App without any PHP code affect the storefront?

The key to performing **template overrides** is to configure the App so that it behaves like a Shopware theme. Once this is done, the App System can use [template overrides](https://developer.shopware.com/docs/guides/plugins/apps/storefront/customize-templates.html) to modify existing storefront templates.

## Code-Along

To follow along, use the following command within the ShopwareStoreTracker directory:

```bash
git checkout tags/storefront_override--start
```

## The `theme.json` File

To use an App as a theme, you need to define a [`theme.json`](https://developer.shopware.com/docs/guides/plugins/apps/storefront/apps-as-themes.html) file inside `[app_root]/Resources/`. This `theme.json` file tells Shopware how your App integrates with the storefront. A minimal example looks like this:

```json
{
	"name": "ShopwareStoreTracker",
	"author": "[your_name_here]",
	"description": {
		"en-GB": "[a_short_description_of_your_theme]"
	},
	"views": [
		"@Storefront",
		"@Plugins",
		"@ShopwareStoreTracker"
	],
	"style": [
    	"@Storefront"
  ]
}
```

<CollapsibleSection title="(Optional) Add a Theme icon">

You can also define a preview icon for your theme by adding a `previewMedia` entry:

```json
{
  "name": "ShopwareStoreTracker",
  "author": "[your_name_here]",
  "description": {
    "en-GB": "[a_short_description_of_your_theme]"
  },
  "previewMedia": "app/storefront/dist/assets/kudosPreview.svg", // <-- PreviewMedia
  "views": [
    "@Storefront",
    "@Plugins",
    "@ShopwareStoreTracker"
  ],
  "style": [
    "@Storefront"
  ]
}
	
```

Download the following icon and add it to your theme at `[app_root]/Resources/app/storefront/dist/assets/kudoPreview.svg`.

![Theme Preview](assets/kudos-regular.svg)

</CollapsibleSection>

<CollapsibleSection title="(Optional) Adding Custom Styles">

The focus of this course is on functionality. However, if you want your result to look the same as in this guide, add the following styles to `[app_root]/Resources/app/storefront/src/scss/base.scss`:

```css
.physical-shop {
  &__list {
    display: flex;
    flex-direction: column;
  }

  &__item {
    margin: 10px 0;
    overflow: hidden;
    background-color: #FFF;

    &:hover .physical-shop__info {
      display: block;
    }
  }

  &__info {
    display: none;
  }
}

.physical-shop__list > li, .product-stock__item {
  padding: 10px;
  background-color: #FFF;
  border-radius: 5px;
  box-shadow: 5px 5px 5px lightgray;
}

.product-stock {
  &__list {
    max-height: 300px;
    overflow-y: scroll;
    display: grid;
    gap: 15px;
    list-style: none;
  }

  &__item > p {
    margin: 0px;

    &__item {
      display: grid;
      grid-auto-flow: column;

      p {
        margin: 0px;
      }
    }
  }
}
```

<Callout title="The base.scss File" type="info">

The `base.scss` file is the entry point of your custom styling. You can organize your styles in multiple folders and files under `[app_root]/Resources/app/storefront/src/scss/`, but all custom files should be imported into the `base.scss` file.

</Callout>

Finally, add the base.scss file to the `style` array in your `theme.json`, otherwise your styles will not be applied:

```json
{
  "name": "ShopwareStoreTracker",
  "author": "[your_name_here]",
  "description": {
    "en-GB": "[a_short_description_of_your_theme]"
  },
  "previewMedia": "app/storefront/dist/assets/kudosPreview.svg",
  "views": [
    "@Storefront",
    "@Plugins",
    "@ShopwareStoreTracker"
  ],
  "style": [
    "@Storefront",
    "app/storefront/src/scss/base.scss" // <-- Add base.scss
  ]
}
```

</CollapsibleSection>

### Specifying a View Loading Order

The `"views"` key in our `theme.json` file defines the order in which storefront templates are loaded. It uses directory aliases, each starting with `@`:

- **`@Storefront`**: Standard templates from Shopware Core
- **`@Plugins`**: Any templates provided by installed plugins
- **`@ShopwareStoreTracker`**: Any templates inside the `ShopwareStoreTracker` app

The templates are loaded in the order they are listed. If the same template appears more than once, the **last entry wins**. In our example, `@ShopwareStoreTracker` is the last item, os its templates have the highest priority and can override everything above.

### Installing Your App as a Theme

After creating the `theme.json`, check if Shopware recognizes your App as a theme. Run the following command in your shop root directory:

```bash
bin/console theme:refresh
```

The `theme:refresh` scans all relevant directories and updates the list of available themes. Next, switch to your App theme with the following command:

```bash
bin/console theme:change
```

You should see an output like this:

```log
Please select a theme:
  [0] Storefront
  [1] ShopwareStoreTracker
>
```

Select `ShopwareStoreTracker` by entering the number and your App is now registered as a theme.

<Callout title="Tip: Hot Reload vs. App Update" type="info">

When developing locally, you can use Shopware's **hot reload** feature for SCSS and storefront JavaScript changes. This allows you to test your changes instantly, without **rebuilding the storefront (`bin/build-storefront.sh`)** or **recompiling the theme (`bin/console theme:compile`)** every time.

Run the following command in your shop root directory:

```bash
bin/watch-storefront.sh
```

This starts a local development server – usually at **`http://localhost:9998`** – that **automatically rebuilds your theme** whenever you **change SCSS or storefront JavaScript files**.

Once you are **done** with your **changes**, you need to run the following command to update your changes in the storefront:

```bash
bin/build-storefront.sh
```

However, if you change **App-specific files** such as:

- Twig template overrides (`[app_root]/Resources/views/`)
- App Scripts (`[app_root]/Resources/scripts`)
- App configuration files (`manifest.xml`, `entities.xml`, `flow.xml`)

You need to run the following command to update your App:

```bash
bin/console app:update ShopwareStoreTracker
```

This ensures that all updated files are saved in the database.

</Callout>

### Troubleshooting

#### Error When Running `theme:refresh`

```shell
In StorefrontPluginConfigurationFactory.php line 167:

\[Shopware\Storefront\Theme\Exception\ThemeCompileException] Unable to compile the theme "ShopwareStoreTracker". Unable to parse theme.json. Message: Syntax error
  
```

**Cause:** Syntax error in your `theme.json` file.

**Solution:** Validate your file in an IDE (e.g., [VSCode](https://code.visualstudio.com/)). Or use an online linter such as [JsonLint](https://jsonlint.com).

#### ShopwareStoreTracker Not Listed in the `theme:change`

Possible causes:

**Cause one**: The App is not installed or not activated.

You can check this with the following command from your shop root directory:

```bash
bin/console app:list
```

If your App is **inactive**, you can **activate** it with the following command:

```bash
bin/console app:activate ShopwareStoreTracker
```

If your App is **missing**, you can **install** it with the following command:

```bash
bin/console app:install ShopwareStoreTracker --activate
```

Alternatively, you can verify the App status directly in your database:

 ```sql
 SELECT `name`, `active` FROM `app`;
```

Expected result:

```log
| ShopwareStoreTracker | 1 |
```

**Cause two**: The `theme.json` file is in the wrong place. It must be located at `[app_root]/Resources/theme.json`.

## Getting Your Template Override Displaying on the Storefront

To create a storefront template override, follow these steps:

1. Navigate to the storefront page you want to modify.
2. Open the Symfony Profiler and locate the Twig template that renders the target area.
3. In your IDE, open that template and choose the Twig block you want to override.
4. In your App, create the override file under `[app_root]/Resources/views/` directory, mirroring the original path.
5. Run an App Update to apply changes.
6. Reload the storefront and verify the result.

<Callout title="Mirroring the File Structure" type="info">

To extend or overwrite an existing template – whether it comes from Shopware core or from another plugin – you need to mirror the file path inside your own plugin.

For example, the product-detail template.:

- The path in Shopware storefront: `vendor/shopware/storefront/Resources/views/storefront/page/product-detail/index.html.twig`
- The path in app: `[app-root]/src/Resources/views/storefront/page/product-detail/index.html.twig`

Now the paths are identical, Shopware will load your template instead of the original one.

</Callout>

### 1: Identifying a Base Template File

Start your Shopware instance locally and open it in the browser (e.g., `http://localhost:8000` with devenv). You should now see the black [Symfony Toolbar](https://symfony.com/doc/current/profiler.html) at the bottom of the page.

<Callout title="Symfony Toolbar Not Showing" type="info">

If the toolbar is missing, try the following command in your shop root directory:

```bash
composer show symfony/web-profiler-bundle
```

There should be an output that shows the profiler bundle.

Also, make sure you are in **development mode** by running the following command:

```bash
bin/console about
```

Check that **Environment** is set to **Development**.

</Callout>

![Storefront Homepage with Symfony Profiler](assets/symfony-profiler.png)

Next, click the status code in the bottom left to open the Symfony Profiler dashboard. This dashboard shows detailed information about the current page.

![Symfony Profiler detailed view](assets/symfony-profiler-detail.png)

In the Profiler sidebar, click on **Twig**. This panel lists all loaded Twig templates. From here, you can start searching for the template you want to override in the next step.

<Callout title="Alternative: Frosh Development Helper" type="info">

Instead of the Symfony Profiler, you can also use the [Frosh Development Helper](https://github.com/FriendsOfShopware/FroshDevelopmentHelper). It shows the template path directly as an annotation in the HTML, making it easier to find the right file.

</Callout>

### 2: Selecting a Twig Template

Opened the Twig tab; you can see all Twig templates used to render the current page, including **their filesystem paths**.

For this example, we will override the **footer**. Use `Ctrl + F` in the Profiler to search for `footer` and locate: `src/Storefront/Resources/views/storefront/layout/footer/footer.html.twig`.

![Symfony footer component](assets/symfony-twig-footer.png)

Copy this path and open the file in your IDE.

<Callout title="Tip: Searching in VSCode" type="info">

In VSCode, press `Ctrl + P` and paste the file path to quickly open the template.

</Callout>

![VSCode Original File](assets/vscode-footer-template.png)

_The base template opened in VSCode. The breadcrumbs at the top show the file path, which we will use in the next step to create our override._

### 3: Setting Up Your Template Override

We have located the original template, so now we need to navigate back to our App Directory and create a template file. This template file will go in the `Resources/views` folder, but will _mirror the green section_ of the **filepath shown below**:

![VSCode Breadcrumb filepath](assets/vscode-breadcrumbs.png)

In our App, template files go under `[app_root]/Resources/views/`, therefore if we combine that path with the green section above, we get `[app_root]/Resources/views/storefront/layout/footer/footer.html.twig`.

Let's create this file now.

#### Add an Override Declaration

Open your new file: `[app_root]/Resources/views/storefront/layout/footer/footer.html.twig`. At the first line, declare that this file overrides the original footer template using [`sw-extends`](https://developer.shopware.com/docs/guides/plugins/plugins/storefront/customize-templates.html#custom-template-content):

```twig
{% sw_extends '@Storefront/storefront/layout/footer/footer.html.twig' %}
```

Next, choose a Twig block from the original template to override. Open the default `footer.html.twig` and scroll until you find a `{% block .... %}` definition.

![Illustration of Twig block selection and relative injection point](assets/block-injection-point.png)

_In this guide we use the block `layout_footer_bottom`_.

After this, redefine this block in your override file. Use the `parent()` function to keep the original content and add your own. Check the following lines:

```twig
{% block layout_footer_bottom %}
  {{ parent() }}
  
  <h1>Check me out I'm custom!</h1>
{% endblock %}
```

This gives you the first visible change in the footer.

### 4. Manifesting Template Changes on the Storefront

Twig template overrides are stored in the database (table `app_template`). To make your changes take effect, run an App Update with the following command in your shop root directory:

```bash
bin/console app:update ShopwareStoreTracker
```

<Callout title="Need a Reminder?" type="info">

If you are unsure how to run an App Update, revisit the [dedicated learning unit](/learn/unit/the-manifest-file#versioningyourapp).

</Callout>

#### (Optional): Verify in the Database

1. To ensure `app:update` was successful, navigate over to Adminer and enter the **shopware** database.
  ![Adminer HomeScreen](assets/adminer-home.png)

2. Navigate to the `app_template` table and click 'Select Data.'
  ![Select App Template Data](assets/adminer-select-data.png)

3. You should see an entry for your footer override with the correct template path.
  ![App template table contents](assets/adminer-app-template-select.png)

### 5. Validating the Template Override

Finally, check the result in the storefront. Reload the start page, you should now see the `<h1>` rendered below the footer content.

![Storefront custom Footer](assets/storefront-custom-footer.png)

## Code-Along (end)

To see what the final result of this learning unit should look like, run the following command:

```bash
git checkout tags/storefront_override--end
```

<Callout title="Removing Working Changes" type="warning">

If you have local changes, you will need to run `git reset --hard HEAD` in the App directory. Be mindful that this command will destroy any local changes!

</Callout>

## App Theme vs. Plugin Theme

Both Apps and Plugins can act as **themes** in Shopware, but their purpose and scope differ.

An **App Theme** is ideal when you only need to **customize storefront templates, styles or content**. It runs in a **sandboxed environment** without any PHP code and is **fully compatible with Shopware Cloud**.

A **Plugin Theme** runs directly inside Shopware and can use **PHP, services, and events**. It offers more flexibility but also requires **server access** and is **not available in cloud environments**.

**In short:**

Use an **App Theme** for **lightweight, secure visual changes**, and a **Plugin Theme** for **deeper, backend-integrated customizations**.

## Summary

In this learning unit, you learned how to:

- **Configure** your App as a **theme** with the `theme.json` file
- Create a **template override** in your App
- **Apply** and verify the **override** in the storefront

With this, you can already adapt the Shopware storefront without creating a separate theme plugin.

In the next learning unit, we will introduce **App Scripts** to attach custom data to your templates and render it on the page.

<Callout title="Tip" type="info">

Keep the [Symfony Profiler](https://symfony.com/doc/current/profiler.html) enabled. It's the easiest way to inspect and analyze storefront templates.

</Callout>
