Customizing Content
Backend Content
- Products
- Categories
- Media
Frontend Content
- Text
- UI Components
Nuxt Content
To manage text and UI components, we use Nuxt Content. Official Nuxt Content Documentation
Structure
These are the default CMS pages that are already available:
content/
├── index.yaml
├── navigation.yaml
├── impressum.md
└── unternehmen/
├── agb.md
├── datenschutz.md
└── zahlung-und-versand.md
You can of course create more and/or override these. You probably want to override the content of your homepage. To do this, proceed as follows:
- Create the mandatory
content.config.tsfile with the content:
export { default } from '@shopbite-de/storefront/content.config'
export * from '@shopbite-de/storefront/content.config'
- Create a new file in your content folder. For example
/content/index.yml - Look at the original file.
- Copy the content into your new file and override the content
You can of course also completely override the content configuration including the data objects and create your own content and structures if you want to redesign your homepage from scratch.
If you want to create additional landing pages, you can do so. By creating a Markdown file in your content folder. The file can be located anywhere in the folder. The file structure is also reflected in the URL path.
For example:
content/meine-landing-page.md-->https://shop.de/meine-landing-pagecontent/unterseite/landing-page-2.md-->https://shop.de/unterseite/unterseiten-landing-page-2
UI Components (Nuxt UI)
You can also use UI components in the Markdown files. You can basically use all UI components from Nuxt UI.
For more information, including styling, see the Official Documentation
Media and performance
The home page loads the hero video and the images from content/index.yml first. Oversized files make the biggest difference in Lighthouse ("Performance", metric LCP), especially on phones.
Hero video and poster
- Add a poster for the video (
hero.poster): the first frame as WebP, 1280 px wide, already blurred (boxblur, the video gets the same blur via CSS), about 20 to 30 KB. The storefront renders the poster as the first image of the page and preloads it. Phones (below 768 px) never load the video, only the poster. - The video itself: 720p, no audio, 5 to 10 seconds, under 1 MB. A 3 MB 1080p video doubles the load time of the home page.
Create both with ffmpeg:
ffmpeg -ss 1 -i hero.mp4 -frames:v 1 -vf "scale=1280:-2,boxblur=4:2" -c:v libwebp -quality 70 hero-poster.webp
ffmpeg -i hero.mp4 -vf "scale=1280:-2" -r 25 -c:v libx264 -crf 28 -preset medium -an -movflags +faststart hero-720p.mp4
hero:
backgroundVideo: https://shop.example.com/media/.../hero-720p.mp4
poster: /hero-poster.webp
The poster can live in the public/ folder of the shop project; the video belongs in the Shopware media.
Hero copy and buttons
The hero shows the USPs (hero.usps) as a compact row at the bottom left, above them the title, the description, a status line and the buttons:
hero.title(optional): the title, e.g. "Italian, freshly delivered." Without it, the shop name (title) is used.hero.headline(optional): small line above the title, e.g. the restaurant name in capitals.- The status line ("Geöffnet bis 23:00 · Lieferung ca. 30 Min") comes automatically from the business hours and the plugin's delivery time.
- The first entry in
hero.linksis the single order button; all further entries render as quiet text buttons.
Directly below the hero, the home page shows the top sellers (products with "Mark as top seller" in Shopware, up to eight) as a horizontal row; a tap opens the product options.
hero:
title: Italienisch, frisch geliefert.
headline: ALTE SCHMIEDE
Information cards
The section "Alle Informationen auf einen Blick" renders the entries of features.features as cards: icon, small category (title), a bold lead line, detail text (description) and an optional action.
kind(optional):hoursfills the lead with today's opening hours ("Heute 11:30–14:30 und 17:30–23:00", "Heute Ruhetag") plus the open/closed status,deliverywith the delivery time from the plugin ("In ca. 30 Minuten bei dir"). Both are live, the text needs no maintenance.lead(optional): the lead line for every other card, e.g. "Tisch nur telefonisch".link(optional):labelandto. Atel:target becomes a call button, anything else a text link. The opening hours in the footer are reachable via#oeffnungszeiten.
features:
features:
- title: Öffnungszeiten
kind: hours
description: Samstags 17:30 - 23:30 Uhr, Dienstag ist Ruhetag.
icon: i-lucide-clock
link:
label: Alle Öffnungszeiten
to: "#oeffnungszeiten"
- title: Reservierung
kind: reservation
lead: Tisch nur telefonisch
description: Bestellungen nehmen wir gerne online oder telefonisch entgegen.
icon: i-lucide-phone
link:
label: 06104 71427 anrufen
to: "tel:+49610471427"
Images
- Category and product images from Shopware need no extra work: Shopware generates thumbnails (400, 800 and 1920 px), the storefront serves them as
srcset, the browser loads the fitting size. - Images from
content/index.yml(CTA background, gallery, customer photos) are loaded as they are. Use WebP up to 1920 px wide, under 200 KB. If the image lives in the Shopware media, use the thumbnail URL (/thumbnail/.../name_1920x545.webp) instead of the original. - The gallery shows images in 4:3 and loads them on scroll.
Cache headers on the object storage
If the Shopware media lives on S3 storage (e.g. Hetzner Object Storage), the storage sends no Cache-Control header by default. Every visit reloads all images and the video. Shopware's media URLs carry a timestamp, so they may be cached for a long time:
# all existing objects (AWS CLI with the Hetzner endpoint)
aws --endpoint-url https://nbg1.your-objectstorage.com s3 cp s3://my-bucket/ s3://my-bucket/ \
--recursive --metadata-directive REPLACE --cache-control "public, max-age=31536000, immutable"
For new uploads set the header in Shopware: shopware.filesystem.public.config.options.CacheControl: "public, max-age=31536000, immutable" in config/packages/shopware.yaml. Check the result with curl -I <media URL>: the response must contain a cache-control line.
Checking
npx lighthouse@12 https://www.my-shop.com/ --only-categories=performance --view
Target: performance above 90 and LCP below 2.5 seconds on a phone.