Hosting the SPA

Magnolia can provide visual authoring for an SPA, PWA or frontend project hosted on any server or meta-framework.

We use SPA as a shorthand for all of these.

For a smooth development experience and flexible deployment, we recommend you to host your SPA externally to Magnolia. It is also possible to deploy an SPA to Magnolia via a light module. Below, we describe both approaches.

An SPA can be hosted anywhere and retrieve content from Magnolia through the REST API. This page, however, is specifically about an SPA that can be edited in the Magnolia Pages app with the Visual SPA Editor technology.

Externally hosted SPA

An SPA can be running or hosted on a remote server. In this configuration, the Magnolia Page Editor loads your frontend project directly from the remote server.

This hosting mode requires version 1.2 or later of the Magnolia angular-editor, react-editor, or vue-editor npm package.

During SPA development, you can specify your local React, Vue or Angular development server running on localhost so that you can take advantage of hot redeploys the instant you make changes to the frontend code.

Configuration

The following properties are key to a correct functioning of your SPA setup:

  • $type

  • baseUrl

  • routeTemplate

The SPA type

For SPA scenarios, $type can be one of the following values:

  • siteSpa - for site-aware SPA templates.

  • spa - for non site-aware SPA templates.

Connecting an external SPA

In your SPA setup, you must specify the URL that will be loaded into the Magnolia Page Editor IFRAME. This is achieved with the baseUrl and routeTemplate properties, which can be defined in two ways:

For more details about the baseUrl and routeTemplate properties, see the table under Common template properties.

See also our headless SPA demo project, showcasing Angular, Vue, React and Next.js (SSR and SSG):

Non site-aware external SPA

For an external SPA that is not site-aware, use spa as the value of the $type property in your page template definition.

Example:

# Since Magnolia 6.2.18, SPA $type aliases are available and the renderType property is optional.
# class: info.magnolia.rendering.spa.renderer.SpaRenderableDefinition
# renderType: spa

$type: spa
title: 'React: Basic'
baseUrl: http://localhost:3100/magnoliaAuthor (1)
routeTemplate: '{{@path}}' (2)
dialog: spa-lm:pages/basic
1 A base URL for the server.
2 A path and any query parameters.

Site-aware external SPA

Use a site prototype definition to configure the baseUrl and routeTemplate SPA properties.

How do I do that? See Configuring a prototype in YAML below.

It can be very convenient to configure baseUrl and routeTemplate in a site template prototype definition rather than in a page template definition.

While maintained in a single site prototype definition, the properties will be applied to every page template in the site. In the page template, the $type must be then set to siteSpa.

Example template definition:

# Since Magnolia 6.2.18, SPA $type aliases are available and the renderType property is optional.
# class: info.magnolia.rendering.spa.renderer.SiteAwareSpaRenderableDefinition
# renderType: site-spa

$type: siteSpa
visible: true
dialog: spa-lm:pages/basic

Example site configuration:

my-site:
  templates:
    prototype:
      baseUrl: http://localhost:3100/magnoliaAuthor
      routeTemplate: '{{@path}}'
      areas:
        extras:
          title: Extras Area
          availableComponents:
            Headline:
              id: spa-lm:components/headline
            Paragraph:
              id: spa-lm:components/paragraph
            List:
              id: spa-lm:components/list
...

Configuring a prototype in YAML

While it is not possible to configure a site definition completely in YAML, you can configure the prototype in YAML and reference it in the site definition. The prototype definition can reside in any module.

To configure the prototype in YAML:

  1. In the site definition:

    1. Set the:

      1. class property to info.magnolia.module.site.templates.ReferencingPrototypeTemplateSettings. This class allows you to use a prototype defined in YAML.

      2. prototypeId to the location of the YAML prototype definition in the <module name>:<relative path to definition> format, for example, travel-demo:pages/prototype.

  2. Remove the prototype node, if it exists.

    Example: travel site definition.

    /<module-name>/sites/travel.yaml
    templates:
      class: info.magnolia.module.site.templates.ReferencingPrototypeTemplateSettings
      prototypeId: travel-demo:pages/prototype
      availability:
        class: com.example.myModule.site.CustomTemplateAvailability
    theme:
      name: travel-demo-theme
    i18n:
      class: info.magnolia.cms.i18n.DefaultI18nContentSupport
      enabled: true
      fallbackLocale: en
      locales:
        en:
          enabled: true
          language: en
        de:
          enabled: true
  3. Create the prototype YAML file in the location defined in the prototypeId property and set the class property to info.magnolia.module.site.templates.PrototypeTemplateDefinition (or a subclass).

Deployment

For deployment, you can specify:

  • The URL of a JavaScript bundle hosted on any server.

  • The URL of a meta-framework server such as NextJS, Gatsby, Nuxt or Scully.

Even projects with statically rendered pages can be authored in Magnolia. Meta-frameworks and static sites are useful for performance, SEO and social previews, among other benefits.

For Next.js Server Side Rendering and Next.js Static Site Generation implementations, the following steps must be taken.

global.mgnlInPageEditor is deprecated and not necessary.

Next.js with Server Side Rendering (SSR)

  1. Use the baseUrl and routeTemplate properties in the page template definitions. Compared with a regular React implementation, Next.js SSR differs in how the code determines the page path to be fetched. In Next.js SSR, it will be read from request URL which is available through context.resolvedUrl.

    Example template

    /light-modules/nextjs-ssr-minimal-lm/templates/pages/basic.yaml (excerpt)
    # Since Magnolia 6.2.18, SPA $type aliases are available and the renderType property is optional.
    # class: info.magnolia.rendering.spa.renderer.SpaRenderableDefinition
    # renderType: spa
    
    $type: spa
    title: 'Next.js SSR: Basic'
    baseUrl: http://localhost:3000
    routeTemplate: '/{language}{{@path}}'
    
    dialog: spa-lm:pages/basic
    ...

Next.js with Static Site Generation (SSG)

In Next.js SSG, in order to have links working for the author instance, you need to make sure that all requests go through a preview API, for example:

/contact => /api/preview?slug=/contact
  1. Create a preview API:

    /spa/nextjs-ssg-minimal/pages/api/preview.js
    // More about Preview Mode: https://nextjs.org/docs/advanced-features/preview-mode
    
    export default function handler(req, res) {
      res.setPreviewData({
        query: req.query,
      });
      res.redirect(req.query.slug);
    }
  2. Again, use the baseUrl and routeTemplate properties in the page template definitions. In SSG, the page path will be read from request URL (preview API) or from a static paths array.

    Example template

    /light-modules/nextjs-ssg-minimal-lm/templates/pages/basic.yaml (excerpt)
    # Since Magnolia 6.2.18, SPA $type aliases are available and the renderType property is optional.
    # class: info.magnolia.rendering.spa.renderer.SpaRenderableDefinition
    # renderType: spa
    
    $type: spa
    title: 'Next.js SSG: Basic'
    baseUrl: http://localhost:3000
    routeTemplate: '/api/preview?slug=/{language}{{@path}}'
    
    dialog: spa-lm:pages/basic
    ...

External SPA and browser compatibility

If you are running SPA editors (React, Angular or Vue) on Magnolia using either Safari or the Brave Browser, you can run into an issue where you see a blank white screen. This issue can be fixed as follows:

Safari

Configure your local SPA development server to use an SSL certificate for the localhost, for example, with the mkcert tool:

  • In your home SPA folder, execute the following command:

    mkcert localhost
  • Configure your local development server to use SSL and the newly created certificate. (Concrete instructions will depend on the framework you are using for your SPA).

  • Change your environment or the light module files to use HTTPS (not just HTTP) to access the local development server. For example, use https://localhost:3000 instead of http://localhost:3000.

  • Restart your local development server.

Brave Browser

Disable the Shields temporarily.

Magnolia-hosted SPA

In this configuration, the Magnolia Page Editor loads your frontend project from files hosted on Magnolia and deployed, typically, in the webresources directory of a light module.

While the externally-hosted SPA is the recommended approach, hosting the SPA in Magnolia has one major advantage: simplicity, in that the inter-dependent SPA and Magnolia configurations are deployed together and to the same server.

The main disadvantages of the Magnolia-hosted approach are the following:

  • The SPA must always be rebuilt and saved to the light module after every change if you want to preview the changes in the Magnolia Page Editor.

  • It is not possible to connect meta-frameworks.

Connecting a Magnolia-hosted SPA

The page template definition specifies the path to the frontend html page generated by the SPA build.

Example
title: 'React: Basic'
dialog: spa-lm:pages/basic
$type: spa
baseUrl: http://localhost:3000
routeTemplate: '/api/preview?slug=/{language}{{@path}}'

The templateScript property is deprecated since Magnolia 6.2.30 for use with the SPA renderer.


Click to show a templateScript example
title: 'React: Basic'
templateScript: /react-minimal-lm/webresources/build/index.html
dialog: spa-lm:pages/basic
renderType: spa
Related topics

Some topics below may take you to a different part of the docs site and away from the current product-docs section.

Feedback

DX Core

×

Location

This widget lets you know where you are on the docs site.

You are currently perusing through the DX Core docs.

Main doc sections

DX Core Headless PaaS Legacy Cloud Incubator modules