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.

A similar functionality has been previously available via the SPA Rendering Extended module. However, that module is now deprecated in favor of this standard bundled functionality.

For an external SPA, use spa as the value of the $type property in your page template definition.

For site-aware SPA rendering, the $type property must be set to siteSpa.

Examples

# 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: Contact'
# templateScript: /react-minimal-lm/webresources/build/index.html
baseUrl: http://localhost:3000
routeTemplate: '{{path}}?lang={language}'
dialog: spa-lm:pages/basic
# 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
baseUrl: http://localhost:3100/magnoliaAuthor
routeTemplate: '{{@path}}'
dialog: mte:pages/pageProperties

Development

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.

Deployment

For deployment, you can specify:

  • 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.

Connecting an external SPA

The page template definition specifies the URL that will be loaded into the Magnolia Page Editor IFRAME. This is achieved with:

  • A baseUrl for the server.

  • A path and any query parameters with a routeTemplate.

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:3000
routeTemplate: '{{@path}}'
dialog: spa-lm:pages/basic

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

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

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
    ...
  2. When inside the Magnolia page editor, set global.mgnlInPageEditor, which is used by the react-editor library.

    Example

    /spa/nextjs-ssr-minimal/pages/[[…​pathname]].js (excerpt)
    ...
     let props = {
        isPagesApp,
        isPagesAppEdit: isPagesApp === 'false',
        basename: isDefaultLanguage ? '' : '/' + currentLanguage,
        pagePath: nodeName + context.resolvedUrl.replace(new RegExp('.*' + nodeName), ''), // Find out page path to fetch from Magnolia
      };
    
      global.mgnlInPageEditor = props.isPagesAppEdit;
    
      if (!isDefaultLanguage) {
        props.pagePath = props.pagePath.replace('/' + currentLanguage, '');
      }
    ...
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
    ...
  3. When inside the Magnolia page editor, set global.mgnlInPageEditor, which is used by the react-editor library.

    Example

    /spa/nextjs-ssg-minimal/pages/[[…​pathname]].js (excerpt)
    ...
     let props = {
        isPagesApp,
        isPagesAppEdit: isPagesApp === 'false',
        basename: isDefaultLanguage ? '' : '/' + currentLanguage,
        pagePath: nodeName + context.resolvedUrl.replace(new RegExp('.*' + nodeName), ''), // Find out page path to fetch from Magnolia
      };
    
      global.mgnlInPageEditor = props.isPagesAppEdit;
    
      if (!isDefaultLanguage) {
        props.pagePath = props.pagePath.replace('/' + currentLanguage, '');
      }
    ...

Minimal Headless SPA Demos

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

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'
templateScript: /react-minimal-lm/webresources/build/index.html
dialog: spa-lm:pages/basic
renderType: spa
Feedback

Headless