Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

AEM Cloudservice - React SPA with Sling Vanity URLs | AEM Community Blog Seeding




AEM Cloudservice - React SPA with Sling Vanity URLs by Sreekanth Choudry Nalabotu


Adobe Experience Manager 2021.9.5899.20210929T093525Z-210800 (Sep 29, 2021)

Create a AEM React SPA supporting Vanity Urls. Otb Vanity Urls are added in Page Properties, saved as jcr:content/sling:vanityPath

1) Add the function getVanityUrls() to get the list of vanity urls using querybuilder before loading the app. VanityURLModelClient extending ModelClient was added as a workaround to not request model.json using the vanity url (eg. this is invalid request http://localhost:4502/eaem-home.model.json). Code in eaem-spa-vanity-urls\ui.frontend\src\index.js facilitates loading of vanity urls into the app...

import 'react-app-polyfill/stable';
import 'react-app-polyfill/ie9';
import 'custom-event-polyfill';

import { Constants, ModelManager } from '@adobe/aem-spa-page-model-manager';
import { createBrowserHistory } from 'history';
import React from 'react';
import { render } from 'react-dom';
import { Router } from 'react-router-dom';
import {ModelClient} from '@adobe/aem-spa-page-model-manager';
import App from './App';
import LocalDevModelClient from './LocalDevModelClient';
import './components/import-components';
import './index.css';

const getVanityUrls = async () => {
const QUERY = "/bin/querybuilder.json?path=/content/eaem-spa-vanity-urls&property=jcr:content/sling:vanityPath&property.operation=exists" +

const response = process.env.REACT_APP_PROXY_ENABLED ? await fetch(QUERY, {
credentials: 'same-origin',
headers: {
'Authorization': process.env.REACT_APP_AEM_AUTHORIZATION_HEADER
}): await fetch(QUERY);

const data = (await response.json()).hits.reduce((current, next) => {
return { ...current, ...{ [next["jcr:path"]]: next["jcr:content"]?.["sling:vanityPath"] } }
}, {});

return data;

class VanityURLModelClient extends ModelClient{
fetch(modelPath) {
//if the path does not start with /content (page editing) or /conf (template editing) return empty model
if (modelPath && !/^\/content|^\/conf/.test(modelPath)) {
return Promise.resolve({});
return super.fetch(modelPath);

const modelManagerOptions = {};

if(process.env.REACT_APP_PROXY_ENABLED) {
modelManagerOptions.modelClient = new LocalDevModelClient(process.env.REACT_APP_API_HOST);
modelManagerOptions.modelClient = new VanityURLModelClient(process.env.REACT_APP_API_HOST);

const renderApp = (vanityUrls) => {
ModelManager.initialize(modelManagerOptions).then(pageModel => {
const history = createBrowserHistory();


document.addEventListener('DOMContentLoaded', () => {
getVanityUrls().then((vanityUrls) => {
}, (err) => {
console.log("Error getting vanity urls", err);

2) Pass the page full url to vanity url mapping object loaded in step above to child pages in eaem-spa-vanity-urls\ui.frontend\src\App.js

Read Full Blog

AEM Cloudservice - React SPA with Sling Vanity URLs


Please use this thread to ask the related questions.

0 Replies