Nuxt and Contentful CMS — Why It’s Hard and How It Can Work

Ninth in a series about migrating from legacy architectures to a modern Nuxt 4 stack.


The Fundamental Tension

Nuxt is a file-based router. You create pages/products/index.vue, and the framework serves it at /products. Routes are known at build time. The directory structure is the URL structure.

Contentful — a headless CMS — is the opposite. Content editors define the URL structure at runtime. They create pages, set slugs, rearrange the information architecture — and the application must serve whatever path they invent, without a code deployment.

This is not a bug — it is a mismatch between two design philosophies. Any team that integrates a headless CMS with Nuxt, Next.js, or any file-based router runs into it.

So why use Nuxt at all? Because the CMS owns the content, not the application. A production web application still needs SSR, authentication, form validation, tracking, server middleware, and dozens of other concerns that only a full application framework covers. The routing mismatch is one problem to solve — not a reason to abandon the framework that solves everything else.


The Solution: A Single Catch-All Route

One file: pages/[...id].vue. Nuxt’s catch-all route matches every path not handled by a more specific route file.

flowchart TB
    subgraph Nuxt_Route_Resolution
        A[/Request: /about/] -->|exists| B[pages/about.vue]
        C[/Request: /service/faq/] -->|exists| D[pages/service/faq.vue]
        E[/Request: /anything/else/] -->|no specific file| F["pages/...id.vue<br/>catch-all"]
    end

The catch-all route does one thing: it queries Contentful for a page entry matching the current URL path. If Contentful returns a page, the component renders it. If not, it returns a 404.

flowchart TB
    A["Browser requests<br/>/products/premium-plan"] --> B["pages/...id.vue"]
    B --> C["Extract path<br/>'/products/premium-plan'"]
    C --> D["GraphQL query<br/>pageByPath(path)"]
    D --> E{Contentful page found?}
    E -- No --> F[Return 404]
    E -- Yes --> G["Contentful returns Page entry<br/>type, title, sections"]
    G --> H["Render ‹app-page :page='page' /›"]
    H --> I["Iterate sections"]
    I --> J["‹component :is=#quot;resolve(section.type)#quot; /›<br/>for each section"]

The CMS owns the URL structure; the application owns the rendering. Neither constrains the other.


Code Generation: From Content Model to Running Components

A CMS page is not a single component — it is a list of content sections, each with a type. The application maps each content type to a Vue component and renders them dynamically. Doing this wiring by hand for dozens of content types does not scale. A code generator reads the Contentful content model schema via GraphQL introspection and produces everything needed.

For every content type, the generator outputs:

  1. A GraphQL query that requests all scalar fields for that type, so the application always fetches exactly what the Contentful schema defines.
  2. A Vue component that receives the Contentful entry as a strongly typed prop, with full TypeScript support for every field out of the box.
flowchart TB
    subgraph Contentful
        P["Page: 'Homepage'"] --> S1[HeroSection]
        P --> S2[TeaserGrid]
        P --> S3[ProductComparison]
        P --> S4[TestimonialCarousel]
        P --> S5[FAQAccordion]
        P --> S6[ContactForm]
    end

    subgraph Generated_Vue_Components
        C1["‹HeroSection :model='...' /›"]
        C2["‹TeaserGrid :model='...' /›"]
        C3["‹ProductComparison :model='...' /›"]
        C4["‹TestimonialCarousel :model='...' /›"]
        C5["‹FAQAccordion :model='...' /›"]
        C6["‹ContactForm :model='...' /›"]
    end

    S1 --> C1
    S2 --> C2
    S3 --> C3
    S4 --> C4
    S5 --> C5
    S6 --> C6

When content editors add a new content type in Contentful, the build pipeline generates the corresponding query and component. The developer only supplies rendering logic and styling — data fetching, types, and component mapping are handled. A content editor adds a new section, and the next page load renders it. No deployment, no PR, no coordination with the development team.


How Content Entries Are Fetched: The Stub-and-Load Pattern

A Contentful content model is a graph. A page references sections, sections reference teasers, teasers reference images and links. Loading the entire graph in one request would hit Contentful’s API response size limits, transfer unnecessary data, and create an all-or-nothing loading bottleneck.

Instead, every Contentful entry is fetched at minimal depth, and every reference is initially just a stub.

What Is a Stub?

A stub is a content entry stripped to two fields: __typename (content type) and sys.id (unique identifier). No title, no body text, no image URLs — just enough to identify what the entry is and where to fetch it.

flowchart LR
    subgraph Full_Entry
        A["__typename: 'Section'"]
        B["sys.id: 'abc123'"]
        C["title: 'Our Services'"]
        D["backgroundColor: 'white'"]
        E["items: [...]"]
        F["sectionText: {...}"]
    end

    subgraph Stub
        G["__typename: 'Section'"]
        H["sys.id: 'abc123'"]
    end

The SysFields GraphQL fragment — automatically applied to all reference fields in generated queries — implements this:

fragment SysFields on Entry {
  __typename
  sys {
    id
  }
}

Minimal-Depth Queries

When a generated query fetches a content type, it requests all scalar fields of that type (strings, numbers, booleans, rich text) but only the SysFields stub for every reference. Collections of references return arrays of stubs.

# Generated Query: cfSection($id)
query cfSection($id: String!) {
  section(id: $id) {
    __typename
    sys { id }
    anchor              # scalar: fetched in full
    backgroundColor     # scalar: fetched in full
    sectionHeadingH2    # scalar: fetched in full
    sectionText { ... } # rich text: fetched in full
    itemsCollection {
      items {
        __typename      # stub: only typename + id
        sys { id }
      }
    }
    mediaCollection {
      items {
        __typename      # stub: only typename + id
        sys { id }
      }
    }
  }
}

Each entry is self-contained and flat. It knows its own data and the identities of its children, but not their content.

How Vue Components Load the Tree

Every generated Vue component follows the same pattern:

  1. It accepts a model prop — which can be either a stub (just __typename and sys.id) or a fully loaded entry.
  2. It calls a generated composable (useCf{ContentType}Entry) that delegates to useOrLoadCfEntry.
  3. useOrLoadCfEntry always triggers a GraphQL fetch by ID — but Apollo’s cache handles the rest.
flowchart TB
    A["Component receives prop<br/>model: stub or full entry"] --> B["useCfSectionEntry(() => props.model)"]
    B --> C["useOrLoadCfEntry(fetchById, () => model)"]
    C --> D{Apollo cache hit?}
    D -- Yes --> E["Return cached data<br/>No network request"]
    D -- No --> F[Fetch from CMS by ID]
    F --> G[Store in Apollo cache]
    G --> E

The component renders its scalar fields and passes each child reference to the next generated component, repeating the cycle.

The Rendering Cascade

On first page load, this creates a cascade of individual fetches, each triggered when a Vue component mounts:

flowchart TB
    A["Browser requests<br/>/products/premium-plan"] --> B["cf-page loads Page entry<br/>(title, slug, stubs for sections, header, footer)"]

    B --> C["cf-section loads Section 'abc123'<br/>(scalars + stubs)"]
    C --> D[cf-teaser loads Teaser 'def456']
    D --> E[cf-image loads Image 'ghi789']
    D --> F[cf-link loads Link 'jkl012']
    C --> G[cf-slider loads Slider 'mno345']

    B --> H[cf-header loads Header 'pqr678']
    B --> I[cf-footer loads Footer 'stu901']

Each component loads exactly one entry from Contentful. The parent passes its child stubs as props; each child component independently calls useOrLoadCfEntry to fetch the full entry by ID. The Vue component tree is the assembled page — it mirrors the content graph through composition, each component owning its own data.

Every useOrLoadCfEntry call goes through useGraphQlQuery, which checks a per-URL cache before hitting GraphQL. On the first SSR render of a URL, each query result is collected in a request-scoped Map and persisted to Redis after render. On subsequent requests, the plugin loads the entire Map in a single read at request start. Each component’s query then short-circuits from the Map — no Apollo Client, no Apollo Server, no Contentful call. This turns 40 individual round-trips into one bulk cache lookup.

flowchart TB
    subgraph First_SSR_Request
        A1[Component query] --> B1[useGraphQlQuery]
        B1 --> C1{URL-scoped Map has entry?}
        C1 -- No --> D1[Call Contentful via GraphQL]
        D1 --> E1[Store result in Map]
    end

    subgraph Persist
        E1 --> F1["Persist Map to Redis<br/>per URL after render"]
    end

    subgraph Subsequent_Requests
        G1[Load Map from Redis at request start] --> H1[Component query]
        H1 --> I1[useGraphQlQuery]
        I1 --> J1{Map has entry?}
        J1 -- Yes --> K1["Return cached result<br/>Skip Apollo/Contentful"]
    end

The Polymorphic Dispatch Component

Reference collections in Contentful are polymorphic — a section’s items can contain teasers, sliders, images, FAQ accordions, or anything else. The generated code routes each stub to the correct component based on __typename:

flowchart TB
    A["cf-section-items-item<br/>receives stub"] --> B{__typename}
    B -- "Teaser" --> C["‹cf-teaser :model='stub' /›"]
    B -- "Slider" --> D["‹cf-slider :model='stub' /›"]
    B -- "Image" --> E["‹cf-image :model='stub' /›"]
    B -- "FAQ" --> F["‹cf-faq :model='stub' /›"]
    B -- other/unknown --> G["‹contentful-error /›"]

Each resolved component calls its own useCf{Type}Entry composable to fetch the full entry by ID. The developer never writes dispatch logic — the code generator produces the complete dispatch tree from the schema.

Apollo Cache as the Deduplication Layer

Every entry is fetched by unique ID, so Apollo’s InMemoryCache deduplicates naturally. If the same entry appears in multiple places — shared footer, reused teaser, global navigation — it is fetched once. Subsequent references reuse the cached result.

Conditional Entries and Deferred Loading

Some Contentful entries have conditions attached — visibility rules evaluated at runtime (time-based, A/B test variants, feature flags). When conditions hide an entry, its children are never loaded. The content tree remains intentionally incomplete.

When a previously cached page is rendered again and a condition changes — making a previously hidden entry visible — the stub for that entry is still present in the parent’s data. The child component mounts, calls useOrLoadCfEntry, and the entry is fetched from Contentful for the first time. The component tree grows to include the newly visible branch.

The page is eventually complete: as conditions change and new branches become visible, the corresponding components mount and load their entries on demand, without requiring a full page reload.

flowchart TB
    A[Parent entry with stub child] --> B{Condition true now?}
    B -- No --> C["Child component not mounted<br/>No fetch"]
    B -- Yes --> D[Child component mounts]
    D --> E[useOrLoadCfEntry for child ID]
    E --> F["Fetch from Contentful<br/>(if not cached)"]
    F --> G[Render newly visible subtree]

Why This Pattern Works

  • No deep queries: Each fetch returns a single, flat object. No nested queries that risk hitting Contentful API limits.
  • Incremental assembly: The page builds itself component by component — each one independently loading its own data. No all-or-nothing loading.
  • Automatic deduplication: Apollo’s cache ensures each entry is fetched exactly once, regardless of how many components reference it.
  • Cache-friendly: Once all components have rendered during SSR, their individual query results are collected and cached as a set per URL (detailed in the following article).
  • Condition-safe: Entries behind conditions are loaded on demand. The tree adapts to runtime state without refetching the entire page.

The Trade-Off: Request Volume

The downside is obvious: many small requests instead of one large one. A page with 40 content entries issues 40 individual GraphQL requests to Contentful on first load. This hits rate limits faster, especially under traffic spikes when multiple server instances render concurrently. Exponential backoff (described below) and aggressive page-level caching (next article) exist specifically to mitigate this. Without caching, this pattern would not scale.


SEO and SSR: The Critical Combination

Content-driven routing only works for SEO if the server renders the full page. Search engines need complete HTML, not a JavaScript shell that fetches content on the client.

Because Nuxt is an SSR framework, the catch-all route executes on the server:

  1. The server receives the request for /products/premium-plan.
  2. The catch-all route’s setup() function runs server-side.
  3. The GraphQL query fetches the page data from Contentful.
  4. Vue renders the full component tree to HTML.
  5. useHead() sets the </code>, <code><meta description></code>, and Open Graph tags from Contentful fields.</li> <li>The browser receives complete, crawlable HTML.</li> </ol> <pre class="mermaid">sequenceDiagram participant User participant Browser participant Nuxt_SSR as Nuxt SSR Server participant Contentful User->>Browser: Request /products/premium-plan Browser->>Nuxt_SSR: HTTP GET /products/premium-plan Nuxt_SSR->>Nuxt_SSR: Match pages/[...id].vue<br/>run setup() Nuxt_SSR->>Contentful: GraphQL pageByPath(path) Contentful-->>Nuxt_SSR: Page data (title, sections, SEO fields) Nuxt_SSR->>Nuxt_SSR: Render Vue tree to HTML<br/>useHead() for meta tags Nuxt_SSR-->>Browser: HTML response<br/>(fully rendered content) Browser-->>User: Display crawlable page</pre> <pre><code class="language-text">Search Engine Crawler receives: ┌─────────────────────────────────────────────┐ │ <html> │ │ <head> │ │ <title>Premium Plan — Our Products</title> │ <meta name="description" │ │ content="Discover our..." /> │ │ <meta property="og:image" ... /> │ │ </head> │ │ <body> │ │ <section class="hero">...</section> │ │ <section class="features">...</section> │ │ <section class="faq">...</section> │ │ <!-- All content rendered, no JS needed --> │ </body> │ │ </html> │ └─────────────────────────────────────────────┘</code></pre> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Redirects from Contentful</h2> <p class="wp-block-paragraph">URLs change. Subscription plans get renamed, pages reorganized, campaigns expire. In traditional architectures, redirect rules live in web server config and need a deployment to change.</p> <p class="wp-block-paragraph">In a large enterprise application, redirect rules can be content entries. Editors create a redirect with a source path and destination. The application loads all redirects into an in-memory map at startup and checks incoming requests against it in server middleware.</p> <p class="wp-block-paragraph">When Contentful publishes a change, a webhook fires and the application refreshes the redirect map — no restart, no deployment. A content editor adds a redirect and sees it take effect within seconds.</p> <pre class="mermaid">flowchart TB A[Content editor creates/updates Redirect entry] --> B[Contentful publishes change] B --> C[Webhook to Application] C --> D[Refresh in-memory redirect map] subgraph Request_Flow E[Incoming HTTP request] --> F{Path in redirect map?} F -- No --> G[Continue normal routing] F -- Yes --> H[Return 301/302 to target URL] end</pre> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Content Security Policy from Contentful</h2> <p class="wp-block-paragraph">The same pattern applies to Content Security Policy. Instead of hardcoding CSP directives in application config, the CSP is stored as a Contentful entry. A server plugin fetches it at runtime and applies it as an HTTP header.</p> <p class="wp-block-paragraph">The security team can update the CSP — add a script source, remove a deprecated domain — without involving developers or waiting for a deployment.</p> <pre class="mermaid">flowchart TB A["Security team edits CSP entry<br/>in Contentful"] --> B[Contentful publishes CSP] B --> C["Webhook or periodic fetch<br/>by server plugin"] C --> D[Update in-memory CSP config] E[Incoming HTTP response] --> F["Attach CSP header<br/>from current config"]</pre> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Rate Limiting and Resilience</h2> <p class="wp-block-paragraph">Contentful’s APIs have rate limits. Hitting them during traffic spikes means pages render without content or return errors.</p> <p class="wp-block-paragraph">The mitigation is <strong>exponential backoff</strong> in the GraphQL client chain:</p> <pre class="mermaid">sequenceDiagram participant Client as GraphQL Client participant Contentful Client->>Contentful: Request Contentful-->>Client: 429 Too Many Requests Client->>Client: Wait 300ms (+ jitter) Client->>Contentful: Retry #1 Contentful-->>Client: 429 Client->>Client: Wait 600ms (+ jitter) Client->>Contentful: Retry #2 Contentful-->>Client: 429 Client->>Client: Wait 1200ms (+ jitter) Client->>Contentful: Retry #3 Contentful-->>Client: 200 OK</pre> <p class="wp-block-paragraph">The retry link handles both 429 (rate limit) and 5xx (server error) responses. Backoff increases exponentially up to 10 seconds. Jitter prevents thundering herd problems when multiple replicas retry at once.</p> <p class="wp-block-paragraph">From the user’s perspective, the page loads slightly slower during a rate limit event. The system self-heals. Logs show warnings, not errors.</p> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Preview Mode: Real-Time WYSIWYG</h2> <p class="wp-block-paragraph">Content editors need to see changes before publishing. Contentful provides a Preview API that returns draft content, but integrating it with an SSR application takes some work.</p> <p class="wp-block-paragraph">The system supports two modes:</p> <figure class="wp-block-table"><table><thead><tr><th>Mode</th><th>API</th><th>Cache</th><th>Use Case</th></tr></thead><tbody><tr><td><strong>Published</strong></td><td>Delivery API</td><td>Aggressive caching</td><td>Production, public traffic</td></tr><tr><td><strong>Preview</strong></td><td>Preview API</td><td>No caching</td><td>CMS editor preview, draft content</td></tr></tbody></table></figure> <p class="wp-block-paragraph">A <code>preview</code> runtime flag switches the entire GraphQL client chain from the Delivery API to the Preview API. When an editor views the application inside Contentful’s preview iframe, they see draft content rendered by the same SSR pipeline that serves production traffic.</p> <p class="wp-block-paragraph">Contentful’s Live Preview SDK goes further: when the editor changes a field in the Contentful sidebar, a <code>postMessage</code> event fires to the application iframe. The application re-renders the affected component — near-real-time WYSIWYG without a page reload.</p> <pre class="mermaid">sequenceDiagram participant Editor as Content Editor participant CMS as Contentful UI participant App as Nuxt App (iframe) participant GraphQL as GraphQL Client Editor->>CMS: Edit field value CMS->>CMS: Use Preview API data CMS-->>App: postMessage(change event) App->>App: Determine affected component App->>GraphQL: Fetch draft content (Preview API<br/>via preview flag) GraphQL-->>App: Updated draft data App-->>Editor: Re-render affected component<br/>inside preview iframe</pre> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">Lessons Learned</h2> <h3 class="wp-block-heading">The catch-all route is an enabler, not a hack</h3> <p class="wp-block-paragraph">A single <code>pages/[...id].vue</code> serving all CMS-driven pages can feel wrong to developers used to explicit route files. It is the correct pattern for content-driven applications. The CMS is the router. The catch-all route is the adapter between the CMS URL model and Nuxt’s file-based routing.</p> <h3 class="wp-block-heading">Content editors should not need developers for URL changes</h3> <p class="wp-block-paragraph">Any system where URL changes require a deployment creates a bottleneck. The dev team becomes a gatekeeper for content operations. Storing redirects and URL structures in the CMS removes that bottleneck.</p> <h3 class="wp-block-heading">Runtime configuration from the CMS is a pattern, not a one-off</h3> <p class="wp-block-paragraph">CSP from the CMS, redirects from the CMS, feature flags from the CMS — the pattern generalizes. Anything that needs to change without a deployment is a candidate for CMS-managed configuration. The requirement is reliable invalidation (webhooks + in-memory refresh) so changes propagate quickly.</p> <h3 class="wp-block-heading">Preview integration is harder than it looks</h3> <p class="wp-block-paragraph">Making SSR work with Contentful’s preview mode means switching the API source, disabling all caches, handling the three-level iframe hierarchy (CMS → application → DevTools), and coordinating live update events across component boundaries. Budget real time for this.</p> <hr class="wp-block-separator has-alpha-channel-opacity"/> <h2 class="wp-block-heading">What’s Next</h2> <ul class="wp-block-list"> <li><strong>Article 6</strong>: <em>Performance Optimization — Chasing That 100% Lighthouse Score</em> — Multi-tier caching, deferred hydration, and the techniques that add up to near-perfect scores.</li> <li><strong>Article 7</strong>: <em>Type-Safe Form Generation from GraphQL Introspection</em> — How the backend schema drives form rendering and validation without any frontend duplication.</li> <li><strong>Article 8</strong>: <em>The Modular Architecture — Independent Building Blocks</em> — How 35+ custom Nuxt modules create a maintainable, extensible system.</li> </ul> <hr class="wp-block-separator has-alpha-channel-opacity"/> <p class="wp-block-paragraph"><em>Munir Husseini is a software architect specializing in full-stack TypeScript, .NET, and cloud-native architectures.</em></p> </div> <div class="taxonomy-category has-link-color wp-elements-4cadf96c0a69bb47d9a8ad686e4653a0 wp-block-post-terms has-text-color has-base-color"><span class="wp-block-post-terms__prefix"><strong>Categories</strong>: </span><a href="https://softwareproduction.eu/?cat=5" rel="tag">Advanced Web App with Nuxt and .NET</a></div> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="padding-left:0;flex-basis:33.33%"><div class="wp-block-template-part"> <div class="wp-block-group is-layout-flow wp-block-group-is-layout-flow" style="padding-top:0;padding-right:0;padding-bottom:0;padding-left:0"> <div class="wp-block-group has-border-color has-background is-layout-flow wp-block-group-is-layout-flow" style="border-color:#222222;border-width:1px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-left-radius:10px;border-bottom-right-radius:10px;background-color:#121212cf;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--20)"><form role="search" method="get" action="https://softwareproduction.eu/" class="wp-block-search__button-inside wp-block-search__icon-button wp-block-search" ><label class="wp-block-search__label screen-reader-text" for="wp-block-search__input-2" >Search</label><div class="wp-block-search__inside-wrapper" ><input class="wp-block-search__input" id="wp-block-search__input-2" placeholder="Search" value="" type="search" name="s" required /><button aria-label="Search" class="wp-block-search__button has-icon wp-element-button" type="submit" ><svg class="search-icon" viewBox="0 0 24 24" width="24" height="24"> <path d="M13 5c-3.3 0-6 2.7-6 6 0 1.4.5 2.7 1.3 3.7l-3.8 3.8 1.1 1.1 3.8-3.8c1 .8 2.3 1.3 3.7 1.3 3.3 0 6-2.7 6-6S16.3 5 13 5zm0 10.5c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5 4.5 2 4.5 4.5-2 4.5-4.5 4.5z"></path> </svg></button></div></form></div> <div class="wp-block-group has-border-color has-background is-layout-flow wp-block-group-is-layout-flow" style="border-color:#222222;border-width:1px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-left-radius:10px;border-bottom-right-radius:10px;background-color:#121212cf;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--20)"> <h4 class="wp-block-heading has-base-color has-text-color has-link-color wp-elements-ce2083e4d4e9d7db3c51defa0923264a" style="margin-top:0;font-style:normal;font-weight:700">Latest Posts</h4> <ul style="margin-top:var(--wp--preset--spacing--30);margin-bottom:var(--wp--preset--spacing--30)" class="wp-block-latest-posts__list wp-block-latest-posts"><li><div class="wp-block-latest-posts__featured-image alignleft"><img loading="lazy" width="150" height="150" src="https://softwareproduction.eu/wordpress/wp-content/uploads/2026/06/type-safe-form-generation-150x150.jpg" class="attachment-thumbnail size-thumbnail wp-post-image" alt="" style="max-width:75px;max-height:75px;" decoding="async" /></div><a class="wp-block-latest-posts__post-title" href="https://softwareproduction.eu/?p=209">Type-Safe Form Generation from GraphQL Introspection</a></li> <li><div class="wp-block-latest-posts__featured-image alignleft"><img loading="lazy" width="150" height="150" src="https://softwareproduction.eu/wordpress/wp-content/uploads/2026/06/ai-assisted-development-150x150.jpg" class="attachment-thumbnail size-thumbnail wp-post-image" alt="" style="max-width:75px;max-height:75px;" decoding="async" /></div><a class="wp-block-latest-posts__post-title" href="https://softwareproduction.eu/?p=208">AI-Assisted Development — MCP, Debug Chatbot, and the Shared Language of the Codebase</a></li> <li><div class="wp-block-latest-posts__featured-image alignleft"><img width="150" height="150" src="https://softwareproduction.eu/wordpress/wp-content/uploads/2026/06/12-ssr-deep-dive-150x150.jpg" class="attachment-thumbnail size-thumbnail wp-post-image" alt="" style="max-width:75px;max-height:75px;" decoding="async" loading="lazy" /></div><a class="wp-block-latest-posts__post-title" href="https://softwareproduction.eu/?p=27">SSR Deep Dive — Hydration, State Replay, and the Cookbook</a></li> <li><div class="wp-block-latest-posts__featured-image alignleft"><img width="150" height="150" src="https://softwareproduction.eu/wordpress/wp-content/uploads/2026/06/20-the-full-picture-150x150.jpg" class="attachment-thumbnail size-thumbnail wp-post-image" alt="" style="max-width:75px;max-height:75px;" decoding="async" loading="lazy" /></div><a class="wp-block-latest-posts__post-title" href="https://softwareproduction.eu/?p=26">The Full Picture — What the New Concept Delivers</a></li> <li><div class="wp-block-latest-posts__featured-image alignleft"><img width="150" height="150" src="https://softwareproduction.eu/wordpress/wp-content/uploads/2026/06/19-load-testing-results-150x150.jpg" class="attachment-thumbnail size-thumbnail wp-post-image" alt="" style="max-width:75px;max-height:75px;" decoding="async" loading="lazy" /></div><a class="wp-block-latest-posts__post-title" href="https://softwareproduction.eu/?p=25">Load Testing Results — 15× Faster, 5× More Capacity</a></li> </ul></div> <div class="wp-block-group has-border-color has-background is-layout-flow wp-block-group-is-layout-flow" style="border-color:#222222;border-width:1px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-left-radius:10px;border-bottom-right-radius:10px;background-color:#121212cf;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--20)"> <h4 class="wp-block-heading has-base-color has-text-color has-link-color wp-elements-bd34943777f85239f7a105773a6c78ab" style="font-style:normal;font-weight:700">Categories</h4> <ul class="wp-block-categories-list wp-block-categories-taxonomy-category wp-block-categories"> <li class="cat-item cat-item-5"><a href="https://softwareproduction.eu/?cat=5">Advanced Web App with Nuxt and .NET</a> </li> <li class="cat-item cat-item-6"><a href="https://softwareproduction.eu/?cat=6">Code Generation and Automation</a> </li> </ul></div> <div class="wp-block-group has-border-color has-background is-layout-flow wp-block-group-is-layout-flow" style="border-color:#222222;border-width:1px;border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-left-radius:10px;border-bottom-right-radius:10px;background-color:#121212cf;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--20)"> <h4 class="wp-block-heading has-base-color has-text-color has-link-color wp-elements-16f29a50c479ae05657a444754d4a977" style="font-style:normal;font-weight:700">Tags</h4> </div> </div> </div></div> </div> </main> <footer class="wp-block-template-part"> <div class="wp-block-group wow animate__animated animate__fadeInUp has-contrast-background-color has-background has-global-padding is-layout-constrained wp-container-core-group-is-layout-6b70955c wp-block-group-is-layout-constrained" style="margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--40)"> <div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-6787811b wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:35%"> <h2 class="wp-block-heading has-base-2-color has-text-color has-link-color wp-elements-69828861e4100c49e060a24728379aaa" style="margin-top:0;margin-bottom:var(--wp--preset--spacing--10);font-size:clamp(14.082px, 0.88rem + ((1vw - 3.2px) * 0.844), 21px);font-style:normal;font-weight:600">Venture Grove Dark</h2> <p class="has-accent-6-color has-text-color has-link-color wp-elements-040c78244bd9e73fb8bd9c46d4ccf667 wp-block-paragraph" style="font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.244), 16px);line-height:1.6">Pellentesque ut neque. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor.</p> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <h2 class="wp-block-heading has-base-2-color has-text-color has-link-color wp-elements-0938ce094fd20e264b43e14f79c7a895" style="margin-top:0;margin-bottom:var(--wp--preset--spacing--10);font-size:clamp(14.082px, 0.88rem + ((1vw - 3.2px) * 0.844), 21px);font-style:normal;font-weight:600">Quick Links</h2> <ul style="font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.244), 16px);" class="wp-block-list has-base-color has-text-color has-link-color wp-elements-8b28c3ba0b23936d4ba018e655d9c443"> <li style="margin-top:0;margin-bottom:6px">Home</li> <li style="margin-top:0;margin-bottom:6px">Services</li> <li style="margin-top:0;margin-bottom:6px">Pages</li> <li style="margin-top:0;margin-bottom:6px">About Us</li> <li style="margin-top:0;margin-bottom:6px">Privacy Policy</li> </ul> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <h2 class="wp-block-heading has-base-2-color has-text-color has-link-color wp-elements-cc2ef11756a9f29d7bed7d4b04798fc6" style="margin-top:0;margin-bottom:var(--wp--preset--spacing--10);font-size:clamp(14.082px, 0.88rem + ((1vw - 3.2px) * 0.844), 21px);font-style:normal;font-weight:600">Get In Touch</h2> <div class="wp-block-group has-base-color has-text-color has-link-color wp-elements-4083b780640abbcacd329888ce38f2d6 is-nowrap is-layout-flex wp-container-core-group-is-layout-6fe3e61f wp-block-group-is-layout-flex"> <figure class="wp-block-image size-full is-resized wp-duotone-ff5520-ffffff-3"><img decoding="async" src="https://softwareproduction.eu/wordpress/wp-content/themes/venture-grove-dark/assets/images/map.png" alt="" class="wp-image-882" style="object-fit:contain;width:21px;height:21px"/></figure> <p class="has-base-color has-text-color has-link-color wp-elements-2eaffef939b6e306f65602025ea4db43 wp-container-content-9cfa9a5a wp-block-paragraph" style="margin-top:0;margin-bottom:0;font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.244), 16px);">Old City Street, USA, 123 New York 35035</p> </div> <div class="wp-block-group has-base-color has-text-color has-link-color wp-elements-139c614eae8ac7b6e199d4c9915a7e4b is-content-justification-left is-nowrap is-layout-flex wp-container-core-group-is-layout-34fa84ec wp-block-group-is-layout-flex"> <figure class="wp-block-image size-full is-resized wp-duotone-ff5520-ffffff-4"><img decoding="async" src="https://softwareproduction.eu/wordpress/wp-content/themes/venture-grove-dark/assets/images/phone.png" alt="" class="wp-image-890" style="object-fit:contain;width:21px;height:21px"/></figure> <p class="has-base-color has-text-color has-link-color wp-elements-5a3a84fbce8e33308f5255f22b0bab7a wp-block-paragraph" style="margin-top:0;margin-bottom:0;font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.244), 16px);">(+1)-123-456-789</p> </div> <div class="wp-block-group has-base-color has-text-color has-link-color wp-elements-f11cfbc28e63bb3910ebc021e527d5de is-nowrap is-layout-flex wp-container-core-group-is-layout-6fe3e61f wp-block-group-is-layout-flex"> <figure class="wp-block-image size-full is-resized wp-duotone-ff5520-ffffff-5"><img decoding="async" src="https://softwareproduction.eu/wordpress/wp-content/themes/venture-grove-dark/assets/images/email.png" alt="" class="wp-image-891" style="object-fit:contain;width:21px;height:21px"/></figure> <p class="has-base-color has-text-color has-link-color wp-elements-2e5d778262d220b7c0fe9f92d1893a90 wp-block-paragraph" style="margin-top:0;margin-bottom:0;font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.244), 16px);">Example@example.com</p> </div> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <h2 class="wp-block-heading has-base-2-color has-text-color has-link-color wp-elements-8a23deadc6711178ab09eb185e726c0b" style="margin-top:0;margin-bottom:var(--wp--preset--spacing--10);font-size:clamp(14.082px, 0.88rem + ((1vw - 3.2px) * 0.844), 21px);font-style:normal;font-weight:600">Social Links</h2> <ul class="wp-block-social-links has-normal-icon-size has-icon-color is-style-logos-only is-content-justification-left is-layout-flex wp-container-core-social-links-is-layout-75231bfc wp-block-social-links-is-layout-flex" style="margin-top:0;margin-bottom:0"><li style="color:#ffffff" class="wp-social-link wp-social-link-facebook has-base-2-color wp-block-social-link"><a href="#" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li> <li style="color:#ffffff" class="wp-social-link wp-social-link-instagram has-base-2-color wp-block-social-link"><a href="#" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,4.622c2.403,0,2.688,0.009,3.637,0.052c0.877,0.04,1.354,0.187,1.671,0.31c0.42,0.163,0.72,0.358,1.035,0.673 c0.315,0.315,0.51,0.615,0.673,1.035c0.123,0.317,0.27,0.794,0.31,1.671c0.043,0.949,0.052,1.234,0.052,3.637 s-0.009,2.688-0.052,3.637c-0.04,0.877-0.187,1.354-0.31,1.671c-0.163,0.42-0.358,0.72-0.673,1.035 c-0.315,0.315-0.615,0.51-1.035,0.673c-0.317,0.123-0.794,0.27-1.671,0.31c-0.949,0.043-1.233,0.052-3.637,0.052 s-2.688-0.009-3.637-0.052c-0.877-0.04-1.354-0.187-1.671-0.31c-0.42-0.163-0.72-0.358-1.035-0.673 c-0.315-0.315-0.51-0.615-0.673-1.035c-0.123-0.317-0.27-0.794-0.31-1.671C4.631,14.688,4.622,14.403,4.622,12 s0.009-2.688,0.052-3.637c0.04-0.877,0.187-1.354,0.31-1.671c0.163-0.42,0.358-0.72,0.673-1.035 c0.315-0.315,0.615-0.51,1.035-0.673c0.317-0.123,0.794-0.27,1.671-0.31C9.312,4.631,9.597,4.622,12,4.622 M12,3 C9.556,3,9.249,3.01,8.289,3.054C7.331,3.098,6.677,3.25,6.105,3.472C5.513,3.702,5.011,4.01,4.511,4.511 c-0.5,0.5-0.808,1.002-1.038,1.594C3.25,6.677,3.098,7.331,3.054,8.289C3.01,9.249,3,9.556,3,12c0,2.444,0.01,2.751,0.054,3.711 c0.044,0.958,0.196,1.612,0.418,2.185c0.23,0.592,0.538,1.094,1.038,1.594c0.5,0.5,1.002,0.808,1.594,1.038 c0.572,0.222,1.227,0.375,2.185,0.418C9.249,20.99,9.556,21,12,21s2.751-0.01,3.711-0.054c0.958-0.044,1.612-0.196,2.185-0.418 c0.592-0.23,1.094-0.538,1.594-1.038c0.5-0.5,0.808-1.002,1.038-1.594c0.222-0.572,0.375-1.227,0.418-2.185 C20.99,14.751,21,14.444,21,12s-0.01-2.751-0.054-3.711c-0.044-0.958-0.196-1.612-0.418-2.185c-0.23-0.592-0.538-1.094-1.038-1.594 c-0.5-0.5-1.002-0.808-1.594-1.038c-0.572-0.222-1.227-0.375-2.185-0.418C14.751,3.01,14.444,3,12,3L12,3z M12,7.378 c-2.552,0-4.622,2.069-4.622,4.622S9.448,16.622,12,16.622s4.622-2.069,4.622-4.622S14.552,7.378,12,7.378z M12,15 c-1.657,0-3-1.343-3-3s1.343-3,3-3s3,1.343,3,3S13.657,15,12,15z M16.804,6.116c-0.596,0-1.08,0.484-1.08,1.08 s0.484,1.08,1.08,1.08c0.596,0,1.08-0.484,1.08-1.08S17.401,6.116,16.804,6.116z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Instagram</span></a></li> <li style="color:#ffffff" class="wp-social-link wp-social-link-youtube has-base-2-color wp-block-social-link"><a href="#" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul> </div> </div> </div> <div class="wp-block-group has-base-2-color has-text-color has-link-color wp-elements-ab53d14c1edf3fb7e47e591f9715f6a4 has-global-padding is-layout-constrained wp-container-core-group-is-layout-90dc1e3c wp-block-group-is-layout-constrained" style="margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--20);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20)"> <div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-9cd8c5ec wp-block-group-is-layout-flex" style="border-top-style:none;border-top-width:0px;padding-top:0"> <p class="has-base-color has-text-color has-link-color has-small-font-size wp-elements-91b820b1f775095116bfb4c7a3cc5cc0 wp-block-paragraph">Designed with <a href="#" rel="nofollow">WordPress</a></p> <p class="has-base-color has-text-color has-link-color has-small-font-size wp-elements-31821815b65b76ed7ab840ee25b15871 wp-block-paragraph">Developed By <a href="#">Themegrove.com</a></p> </div> <p class="venture-grove-dark-scrool-top wp-block-paragraph"></p> </div> </footer></div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-ff5520-ffffff-3"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="1 1" /><feFuncG type="table" tableValues="0.33333333333333 1" /><feFuncB type="table" tableValues="0.12549019607843 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-ff5520-ffffff-4"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="1 1" /><feFuncG type="table" tableValues="0.33333333333333 1" /><feFuncB type="table" tableValues="0.12549019607843 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" focusable="false" role="none" style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;" ><defs><filter id="wp-duotone-ff5520-ffffff-5"><feColorMatrix color-interpolation-filters="sRGB" type="matrix" values=" .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 .299 .587 .114 0 0 " /><feComponentTransfer color-interpolation-filters="sRGB" ><feFuncR type="table" tableValues="1 1" /><feFuncG type="table" tableValues="0.33333333333333 1" /><feFuncB type="table" tableValues="0.12549019607843 1" /><feFuncA type="table" tableValues="1 1" /></feComponentTransfer><feComposite in2="SourceGraphic" operator="in" /></filter></defs></svg><script data-wp-router-options="{"loadOnClientNavigation":true}" fetchpriority="low" id="@wordpress/block-library/navigation/view-js-module" src="https://softwareproduction.eu/wordpress/wp-includes/js/dist/script-modules/block-library/navigation/view.min.js?ver=96a846e1d7b789c39ab9" type="module"></script> <script id="venture-grove-dark-main-script-js" src="https://softwareproduction.eu/wordpress/wp-content/themes/venture-grove-dark/assets/js/script.js?ver=1.0.0"></script> <script id="venture-grove-main-script-js" src="https://softwareproduction.eu/wordpress/wp-content/themes/venture-grove/assets/js/script.js?ver=1.0.0"></script> <script id="slick-slider-js" src="https://softwareproduction.eu/wordpress/wp-content/plugins/gutentools//assets/vendors/slick/slick.min.js?ver=1.8.0"></script> <script id="waypoint-js" src="https://softwareproduction.eu/wordpress/wp-content/plugins/gutentools//assets/vendors/count-up/jquery.waypoints.min.js?ver=1.0.5"></script> <script id="jquery-countup-js" src="https://softwareproduction.eu/wordpress/wp-content/plugins/gutentools//assets/vendors/count-up/jquery.countup.min.js?ver=1.0.5"></script> <script id="jquery-ticker-js" src="https://softwareproduction.eu/wordpress/wp-content/plugins/gutentools//assets/vendors/news-ticker-controls-acme/js/acmeticker.min.js?ver=null"></script> <script id="jetpack-stats-js-before"> _stq = window._stq || []; _stq.push([ "view", {"v":"ext","blog":"255179396","post":"16","tz":"0","srv":"softwareproduction.eu","j":"1:15.8"} ]); _stq.push([ "clickTrackerInit", "255179396", "16" ]); //# sourceURL=jetpack-stats-js-before </script> <script data-wp-strategy="defer" defer id="jetpack-stats-js" src="https://stats.wp.com/e-202623.js"></script> <script id="wp-emoji-settings" type="application/json"> {"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://softwareproduction.eu/wordpress/wp-includes/js/wp-emoji-release.min.js?ver=7.0"}} </script> <script type="module"> /*! This file is auto-generated */ const a=JSON.parse(document.getElementById("wp-emoji-settings").textContent),o=(window._wpemojiSettings=a,"wpEmojiSettingsSupports"),s=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const a=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===a[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,a){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!a(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,a){let r;const o=(r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),s=(o.textBaseline="top",o.font="600 32px Arial",{});return e.forEach(e=>{s[e]=t(o,e,n,a)}),s}function r(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}a.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),c.toString(),p.toString()].join(",")+"));",a=new Blob([e],{type:"text/javascript"});const r=new Worker(URL.createObjectURL(a),{name:"wpTestEmojiSupports"});return void(r.onmessage=e=>{i(n=e.data),r.terminate(),t(n)})}catch(e){}i(n=f(s,u,c,p))}t(n)}).then(e=>{for(const n in e)a.supports[n]=e[n],a.supports.everything=a.supports.everything&&a.supports[n],"flag"!==n&&(a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&a.supports[n]);var t;a.supports.everythingExceptFlag=a.supports.everythingExceptFlag&&!a.supports.flag,a.supports.everything||((t=a.source||{}).concatemoji?r(t.concatemoji):t.wpemoji&&t.twemoji&&(r(t.twemoji),r(t.wpemoji)))}); //# sourceURL=https://softwareproduction.eu/wordpress/wp-includes/js/wp-emoji-loader.min.js </script> </body> </html> <!-- Page supported by LiteSpeed Cache 7.8.1 on 2026-06-07 03:31:03 -->