An example single-page app, written in React, that consumes content from AEM Headless GraphQL APIs.
View exampleAEM Headless single-page app (SPA) deployments involve JavaScript-based applications built using frameworks such as React or Vue, that consume and interact with content in AEM in a headless manner.
Deploying a SPA that interacts AEM in a headless manner involves hosting the SPA and making it accessible via a web browser.
A SPA is comprised of a collection of native web resources: HTML, CSS, and JavaScript. These resources are generated during the build process (for example, npm run build
) and deployed to a host for consumption by end users.
There are various hosting options depending upon your organization’s requirements:
Cloud providers such as Azure or AWS.
On premise hosting in a corporate data center
Front-end hosting platforms such as AWS Amplify, Azure App Service, Netlify, Heroku, Vercel, etc.
The main consideration when hosting a SPA that interacts with AEM headless, is if the SPA is accessed via AEM’s domain (or host), or on a different domain. The reason is SPAs are web applications running in web browsers, and thus are subject to web browsers security policies.
A SPA and AEM share domains when both are access by end users from the same domain. For example:
https://wknd.site/
https://wknd.site/spa
Since both AEM and the SPA are accessed from the same domain, web browsers allow the SPA to make XHR to AEM Headless endpoints without the need for CORS, and allow the sharing of HTTP cookies (such as AEM’s login-token
cookie).
How SPA and AEM traffic is routed on the shared domain, is up to you: CDN with multiple origins, HTTP server with reverse proxy, hosting the SPA directly in AEM, and so on.
Below are deployment configurations required for SPA production deployments, when hosted on the same domain as AEM.
SPA connects to | AEM Author | AEM Publish | AEM Preview |
---|---|---|---|
Dispatcher filters | ✘ | ✔ | ✔ |
Cross-origin resource sharing (CORS) | ✘ | ✘ | ✘ |
AEM hosts | ✘ | ✘ | ✘ |
A SPA and AEM have different domains when they are accessed by end users from the different domain. For example:
https://wknd.site/
https://wknd-app.site/
Since AEM and the SPA are accessed from different domains, web browsers enforce security policies such as cross-origin resource sharing (CORS), and prevent sharing HTTP cookies (such as AEM’s login-token
cookie).
Below are deployment configurations required for SPA production deployments, when hosted on a different domain than AEM.
SPA connects to | AEM Author | AEM Publish | AEM Preview |
---|---|---|---|
Dispatcher filters | ✘ | ✔ | ✔ |
Cross-origin resource sharing (CORS) | ✔ | ✔ | ✔ |
AEM hosts | ✔ | ✔ | ✔ |
In this example, the SPA is deployed to a Netlify domain (https://main--sparkly-marzipan-b20bf8.netlify.app/
) and the SPA consumes AEM GraphQL APIs from the AEM Publish domain (https://publish-p65804-e666805.adobeaemcloud.com
). The below screenshots highlight the CORS requirement.
The SPA is served from a Netlify domain, but makes an XHR call to AEM GraphQL APIs on a different domain. This cross-site request requires CORS to be set up on AEM to allow request from the Netlify domain to access its content.
Inspecting the XHR request to the AEM GraphQL API, the Access-Control-Allow-Origin
is present, indicating to the web browser that AEM allows request from this Netlify domain to access its content.
If the AEM CORS was missing or did not include the Netlify domain, the web browser would fail the XHR request, and report a CORS error.
Adobe provides an example single-page app coded in React.
An example single-page app, written in React, that consumes content from AEM Headless GraphQL APIs.
View exampleAn example single-page app, written in Next.js, that consumes content from AEM Headless GraphQL APIs.
View example