---
title: "Academy Article"
canonical_url: "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code"
locale: en
meta:
  "og:title": "Academy Article"
---

[Go to home](https://academy.laioutr.com/en)

- [For developers](https://academy.laioutr.com/en/bereiche/for-developers)

- [Developer start](https://academy.laioutr.com/en/leitfaeden/developer-start)

- [Performance and technical SEO in code](https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code)

# Performance and technical SEO in code

Laioutr frontends render on the server, cache data in Orchestr and deliver media through the Laioutr CDN with transformations at the edge. Canonical, hreflang and Schema.org data are generated automatically; developers control HTTP caching via routeRules and how the entry script loads.

## Before you start

<dl>

<dt>Duration</dt>
<dd>10 min</dd></dl>

Last reviewed on October 15, 2026

The goal is good Core Web Vitals: LCP under 1.2 s, INP under 80 ms and CLS under 0.02. Several layers work together for this.

### Rendering and caching

SSR is enabled by default, HTTP caching is not. Data passes three cache layers: the Orchestr entity cache on the server, the HTTP or CDN cache at the edge (via `routeRules`) and an LRU store in the browser. Personalised content such as the cart count belongs on the client, so cached HTML stays the same for everyone.

### Media

The Laioutr CDN gives every project its own bucket and hostname, resizes and converts images at the edge and caches objects immutably.

### Technical SEO

Frontend Core sets canonical, hreflang alternates, `og:locale` and `<html lang>` on every page. Every page carries one Schema.org graph as JSON-LD: organisation, breadcrumbs, FAQ, product and category pages. Title, description and robots come from the SEO fields in Studio.

## Step by step

1. 1 ### Step 1: Enable HTML caching

   Set a short CDN TTL for `'/**'` under `routeRules` in `nuxt.config.ts`, for example `public, max-age=0, s-maxage=15, must-revalidate`. Exclude checkout, cart and login with `private, no-store`.
2. 2 ### Step 2: Separate markets and languages

   With several markets on one domain, set a `Vary` header for the relevant request headers. Language prefixes in the path or separate domains split the cache on their own.
3. 3 ### Step 3: Load the entry script after first paint

   Set `"loading": "after-paint"` under `config.entryScript` in `laioutrrc.json`. The JavaScript then no longer competes with the largest image; the setting applies to production builds only.
4. 4 ### Step 4: Add structured data

   Call `useStructuredData()` in custom Sections with nodes from `@unhead/schema-org/vue` or `toSchemaOrgProduct()`, and check the result with Google's Rich Results Test.

## Frequently asked questions

Why does the CDN not cache HTML pages?

Without custom `routeRules`, the frontend sends no `Cache-Control` headers. Only a rule makes HTML cacheable at the CDN.

Does Schema.org require an extra module?

No. The SEO Essentials app and the Sections for breadcrumbs, FAQ, product detail and product listings write their nodes into one shared graph. Each of these Sections has a checkbox for it.

How can titles or hreflang tags be adjusted in code?

Through the `frontend-core:page-head:resolve` hook. It exposes the computed values for SEO meta and locale tags and allows adding, changing or removing them.

## Related

- [Performance: caching and Orchestr](https://academy.laioutr.com/en/artikel/performance-caching-and-orchestr)6 min

  Laioutr speeds up storefronts with three cache layers: the Orchestr entity cache on the server, the HTTP cache at the edge and a store in the browser. Together they keep repeated requests from putting load on backends.
- [SEO basics before launch](https://academy.laioutr.com/en/artikel/seo-basics-before-launch)10 min

  Before going live, every important page needs a meta title, a description and the right robots value, the organisation belongs in the structured data, and old URLs redirect to new ones. The team then checks robots.txt, sitemap and rich results on the live domain.
- [Multilingual SEO and hreflang](https://academy.laioutr.com/en/artikel/multilingual-seo-hreflang)6 min

  Laioutr sets canonical, hreflang alternates, x-default, og:locale and the lang attribute on every page automatically. They are based on the languages under Translations, the domains under Markets and the translated page paths in Studio.
- [Deliver images through the Laioutr CDN](https://academy.laioutr.com/en/artikel/deliver-images-through-the-laioutr-cdn)4 min

  The Laioutr CDN stores a project's images in a dedicated store and delivers them from the project's own hostname. Size and format are adapted at the edge on request, and delivered images stay cached for a long time.

## Learn it in a lesson

- [Performance and technical SEO](https://academy.laioutr.com/en/lektionen/developer-performance-and-technical-seo)12 min

## [Developer start](https://academy.laioutr.com/en/leitfaeden/developer-start)

Search this guide

1. [Set up a local development environment](https://academy.laioutr.com/en/artikel/set-up-a-local-development-environment)15 min
2. [The Laioutr CLI: commands and authentication](https://academy.laioutr.com/en/artikel/laioutr-cli-commands-and-authentication)6 min
3. [Build and release a first custom app](https://academy.laioutr.com/en/artikel/build-and-release-a-first-custom-app)20 min
4. [Define custom Sections and Blocks for Studio](https://academy.laioutr.com/en/artikel/define-custom-sections-and-blocks-for-studio)15 min
5. [Orchestr: entities, queries, actions and resolvers](https://academy.laioutr.com/en/artikel/orchestr-entities-queries-actions-and-resolvers)8 min
6. [Declare content collections in code](https://academy.laioutr.com/en/artikel/declare-content-collections-in-code)15 min
7. [Performance and technical SEO in code](https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code)10 min

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://academy.laioutr.com/#website",
      "@type": "WebSite",
      "inLanguage": "en",
      "name": "Default",
      "url": "https://academy.laioutr.com/",
      "translationOfWork": {
        "@id": "https://academy.laioutr.com/#website"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#webpage",
      "name": "Academy Article",
      "url": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code",
      "@type": [
        "WebPage",
        "FAQPage"
      ],
      "breadcrumb": {
        "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#breadcrumb"
      },
      "isPartOf": {
        "@id": "https://academy.laioutr.com/#website"
      },
      "mainEntity": [
        {
          "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/1"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/2"
        },
        {
          "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/3"
        }
      ],
      "potentialAction": [
        {
          "@type": "ReadAction",
          "target": [
            "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code"
          ]
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#breadcrumb",
      "@type": "BreadcrumbList",
      "itemListElement": [
        {
          "@type": "ListItem",
          "name": "Home",
          "item": "https://academy.laioutr.com/en",
          "position": 1
        },
        {
          "@type": "ListItem",
          "name": "For developers",
          "item": "https://academy.laioutr.com/en/bereiche/for-developers",
          "position": 2
        },
        {
          "@type": "ListItem",
          "name": "Developer start",
          "item": "https://academy.laioutr.com/en/leitfaeden/developer-start",
          "position": 3
        },
        {
          "@type": "ListItem",
          "name": "Performance and technical SEO in code",
          "item": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code",
          "position": 4
        }
      ]
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/1",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Why does the CDN not cache HTML pages?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>Without custom <code>routeRules</code>, the frontend sends no <code>Cache-Control</code> headers. Only a rule makes HTML cacheable at the CDN.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/2",
      "@type": "Question",
      "inLanguage": "en",
      "name": "Does Schema.org require an extra module?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>No. The SEO Essentials app and the Sections for breadcrumbs, FAQ, product detail and product listings write their nodes into one shared graph. Each of these Sections has a checkbox for it.</p>"
      }
    },
    {
      "@id": "https://academy.laioutr.com/en/artikel/performance-and-technical-seo-in-code#/schema/question/3",
      "@type": "Question",
      "inLanguage": "en",
      "name": "How can titles or hreflang tags be adjusted in code?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<p>Through the <code>frontend-core:page-head:resolve</code> hook. It exposes the computed values for SEO meta and locale tags and allows adding, changing or removing them.</p>"
      }
    }
  ]
}
```
