Repository: single-spa/single-spa-layout
Pull request #21 (2020-05-15 20:10:53)

Renaming routes to children, in preparation for dom element children.
This is in preparation for supporting dom elements as children of routes


Patch:
diff --git a/README.md b/README.md
index 579eae8..cfcdf50 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
 Layout engine for single-spa applications
 
 ## Project Goal
+
 Single-spa layout attempts to solve the following problems:
+
 - Controlling where each single-spa application is rendered in the DOM
 - Reordering the single-spa applications during route changes
 - Embracing a more familiar route based registration of applications
@@ -16,11 +18,13 @@ Single-spa layout attempts to solve the following problems:
 ## API
 
 ### Overview
+
 1. [contstruct routes](#Constructing-Routes)
 2. construct applications from routes
 3. register applications
 4. construct layout engine
 5. call `start()` from the `single-spa` package
+
 ```js
 // root-config.js
 import { registerApplication, start } from 'single-spa';
@@ -33,15 +37,17 @@ const layoutEngine = constructLayoutEngine({routes, applications})
 start()
 ```
 
-
 ### Constructing Routes
+
 single-spa-layout supports two different sytanxes defining applications and routes at this time:
+
 - [JSX](#JSX) (compiles to JSON syntax)
 - [JSON](#JSON)
 
 #### JSX
+
 ```jsx
-<router mode='history' base='/' containerEl='#selector'>
+<router mode="history" base="/" containerEl="#selector">
   <application name="@org/navbar" />
   <route path="/app1">
     <application name="@org/main-sidenav" />
@@ -59,17 +65,18 @@ single-spa-layout supports two different sytanxes defining applications and rout
 ```
 
 #### JSON
+
 ```js
 const routes = {
   mode: "history",
   base: "/",
   containerEl: "#selector",
-  routes: [
+  children: [
     { type: "application", name: "@org/navbar" },
     {
       type: "route",
       path: "app1",
-      routes: [
+      children: [
         { type: "application", name: "@org/main-sidenav" },
         { type: "application", name: "@org/app1" },
       ],
@@ -77,7 +84,7 @@ const routes = {
     {
       type: "route",
       path: "app2",
-      routes: [
+      children: [
         { type: "application", name: "@org/main-sidenav" },
         { type: "application", name: "@org/app2" },
       ],
@@ -85,9 +92,9 @@ const routes = {
     {
       type: "route",
       path: "settings",
-      routes: [{ type: "application", name: "@org/settings" }],
+      children: [{ type: "application", name: "@org/settings" }],
     },
     { type: "application", name: "@org/footer" },
   ],
-}
+};
 ```
diff --git a/src/constructApplications.js b/src/constructApplications.js
index 4f2d4c2..6bbc977 100644
--- a/src/constructApplications.js
+++ b/src/constructApplications.js
@@ -17,7 +17,7 @@ import { resolvePath } from "./matchRoute";
  */
 export function constructApplications({ routes, loadApp }) {
   const applicationMap = {};
-  recurseRoutes(applicationMap, routes.base, {}, routes.routes);
+  recurseRoutes(applicationMap, routes.base, {}, routes.children);
 
   /**
    * @type {Array<{
@@ -61,27 +61,27 @@ export function constructApplications({ routes, loadApp }) {
  * @param {ApplicationMap} applicationMap
  * @param {string} path
  * @param {object} props
- * @param {Array<import('./constructRoutes').Route>} routes
+ * @param {Array<import('./constructRoutes').RouteChild>} children
  * @returns void
  */
-function recurseRoutes(applicationMap, path, props, routes) {
-  routes.forEach((route) => {
-    if (route.type === "application") {
-      if (!applicationMap[route.name]) {
-        applicationMap[route.name] = [];
+function recurseRoutes(applicationMap, path, props, children) {
+  children.forEach((child) => {
+    if (child.type === "application") {
+      if (!applicationMap[child.name]) {
+        applicationMap[child.name] = [];
       }
 
-      applicationMap[route.name].push({
+      applicationMap[child.name].push({
         path,
-        props: mergeProps(props, route.props),
+        props: mergeProps(props, child.props),
       });
     } else {
-      const resolvedPath = resolvePath(path, route.path);
+      const resolvedPath = resolvePath(path, child.path);
       recurseRoutes(
         applicationMap,
         resolvedPath,
-        mergeProps(props, route.props),
-        route.routes
+        mergeProps(props, child.props),
+        child.children
       );
     }
   });
diff --git a/src/constructLayoutEngine.js b/src/constructLayoutEngine.js
index 382d74a..77ce8d1 100644
--- a/src/constructLayoutEngine.js
+++ b/src/constructLayoutEngine.js
@@ -1,4 +1,4 @@
-import { matchRoute, resolvePath } from "./matchRoute";
+import { resolvePath } from "./matchRoute";
 import { inBrowser } from "./environment-helpers";
 
 /**
@@ -82,10 +82,10 @@ export function constructLayoutEngine({
         ? document.querySelector(resolvedRoutes.containerEl)
         : resolvedRoutes.containerEl;
 
-    recurseRoutes({
+    recurseChildren({
       path,
       pathMatch: baseWithoutSlash,
-      routes: resolvedRoutes.routes,
+      children: resolvedRoutes.children,
       parentContainer,
       shouldMount: true,
     });
@@ -107,7 +107,7 @@ export function constructLayoutEngine({
  * @typedef {{
  * path: string,
  * pathMatch: string,
- * routes: Array<import('./constructRoutes').Route>,
+ * children: Array<import('./constructRoutes').RouteChild>,
  * parentContainer: HTMLElement,
  * previousSibling?: HTMLElement,
  * shouldMount: boolean;
@@ -119,18 +119,18 @@ export function constructLayoutEngine({
  * @param {DomChangeInput} input
  * @returns {HTMLElement}
  */
-function recurseRoutes({
+function recurseChildren({
   path,
   pathMatch,
-  routes,
+  children,
   parentContainer,
   previousSibling,
   shouldMount,
 }) {
-  routes.forEach((route) => {
-    if (route.type === "application") {
-      const applicationContainer = getContainerEl(parentContainer, route);
-      const applicationElement = getApplicationElement(route.name);
+  children.forEach((child) => {
+    if (child.type === "application") {
+      const applicationContainer = getContainerEl(parentContainer, child);
+      const applicationElement = getApplicationElement(child.name);
 
       if (shouldMount) {
         if (
@@ -150,12 +150,12 @@ function recurseRoutes({
         }
       }
     } else {
-      const childPathMatch = resolvePath(pathMatch, route.path);
-      previousSibling = recurseRoutes({
+      const childPathMatch = resolvePath(pathMatch, child.path);
+      previousSibling = recurseChildren({
         path,
         pathMatch: childPathMatch,
-        routes: route.routes,
-        parentContainer: getContainerEl(parentContainer, route),
+        children: child.children,
+        parentContainer: getContainerEl(parentContainer, child),
         previousSibling,
         shouldMount: shouldMount && path.startsWith(childPathMatch),
       });
@@ -168,23 +168,23 @@ function recurseRoutes({
 /**
  *
  * @param {HTMLElement} parentContainer
- * @param {import('./constructRoutes').Route} route
+ * @param {import('./constructRoutes').RouteChild} child
  * @returns {HTMLElement}
  */
-function getContainerEl(parentContainer, route) {
+function getContainerEl(parentContainer, child) {
   let container;
 
-  if (route.containerEl) {
-    if (typeof route.containerEl === "string") {
+  if (child.containerEl) {
+    if (typeof child.containerEl === "string") {
       // try scoped/nested within parentContainer
-      container = parentContainer.querySelector(route.containerEl);
+      container = parentContainer.querySelector(child.containerEl);
 
       if (!container) {
         // otherwise allow for reaching outside of parentContainer
-        container = document.querySelector(route.containerEl);
+        container = document.querySelector(child.containerEl);
       }
     } else {
-      container = route.containerEl;
+      container = child.containerEl;
     }
   }
 
@@ -197,7 +197,7 @@ function getContainerEl(parentContainer, route) {
 
 /**
  *
- * @param {import('./constructRoutes').Route} route
+ * @param {import('./constructRoutes').RouteChild} child
  * @returns {HTMLElement}
  */
 function getApplicationElement(name) {
diff --git a/src/constructRoutes.js b/src/constructRoutes.js
index 94e66f4..a282379 100644
--- a/src/constructRoutes.js
+++ b/src/constructRoutes.js
@@ -16,25 +16,25 @@ import { inBrowser } from "./environment-helpers.js";
  * base?: string;
  * containerEl?: ContainerEl;
  * disableWarnings?: boolean;
- * routes: Array<Route>;
+ * children: Array<RouteChild>;
  * }} InputRoutesConfigObject
  *
  * @typedef {{
  * mode: string;
  * base: string;
  * containerEl: ContainerEl;
- * routes: Array<Route>;
+ * children: Array<RouteChild>;
  * sourceElement?: HTMLElement | import('parse5').DefaultTreeDocument;
  * }} ResolvedRoutesConfig
  *
- * @typedef {UrlRoute | Application} Route
+ * @typedef {UrlRoute | Application} RouteChild
  *
  * @typedef {string | HTMLElement | import('parse5').Element} ContainerEl
  *
  * @typedef {{
  * type: string;
  * path: string;
- * routes: Array<Route>;
+ * children: Array<RouteChild>;
  * }} UrlRoute
  *
  * @typedef {{
@@ -70,7 +70,7 @@ function domToRoutesConfig(domElement) {
 
   const result = {
     sourceElement: domElement,
-    routes: [],
+    children: [],
   };
 
   if (getAttribute(domElement, "mode")) {
@@ -82,7 +82,7 @@ function domToRoutesConfig(domElement) {
   }
 
   for (let i = 0; i < domElement.childNodes.length; i++) {
-    result.routes.push(
+    result.children.push(
       ...elementToJson(domElement.childNodes[i], domElement.parentNode)
     );
   }
@@ -124,12 +124,14 @@ function elementToJson(element, parentElement) {
     const route = {
       type: "route",
       path: getAttribute(element, "path"),
-      routes: [],
+      children: [],
       containerEl: parentElement,
     };
     setProps(element, route, ["path"]);
     for (let i = 0; i < element.childNodes.length; i++) {
-      route.routes.push(...elementToJson(element.childNodes[i], parentElement));
+      route.children.push(
+        ...elementToJson(element.childNodes[i], parentElement)
+      );
     }
     return [route];
   } else if (element.childNodes) {
@@ -175,7 +177,7 @@ function validateAndSanitize(routesConfig) {
   validateKeys(
     "routesConfig",
     routesConfig,
-    ["mode", "base", "containerEl", "routes", "disableWarnings"],
+    ["mode", "base", "containerEl", "children", "disableWarnings"],
     disableWarnings
   );
 
@@ -197,9 +199,9 @@ function validateAndSanitize(routesConfig) {
     routesConfig.base = "/";
   }
 
-  validateArray("routesConfig.routes", routesConfig.routes, validateRoute);
+  validateArray("routesConfig.children", routesConfig.children, validateChild);
 
-  function validateRoute(route, propertyName) {
+  function validateChild(route, propertyName) {
     validateObject(propertyName, route);
     validateEnum(propertyName, route.type, ["application", "route"]);
 
@@ -210,11 +212,11 @@ function validateAndSanitize(routesConfig) {
       validateKeys(
         propertyName,
         route,
-        ["type", "path", "routes"],
+        ["type", "path", "children"],
         disableWarnings
       );
       validateString(`${propertyName}.path`, route.path);
-      validateArray(`${propertyName}.routes`, route.routes, validateRoute);
+      validateArray(`${propertyName}.children`, route.children, validateChild);
     }
   }
 
diff --git a/src/matchRoute.js b/src/matchRoute.js
index ac80f76..2a3d988 100644
--- a/src/matchRoute.js
+++ b/src/matchRoute.js
@@ -13,13 +13,13 @@ export function matchRoute(resolvedRoutesConfig, pathMatch) {
   );
 
   if (pathMatch.startsWith(baseWithoutSlash)) {
-    result.routes = recurseRoutes(
+    result.children = recurseRoutes(
       pathMatch,
       resolvedRoutesConfig.base,
-      resolvedRoutesConfig.routes
+      resolvedRoutesConfig.children
     );
   } else {
-    result.routes = [];
+    result.children = [];
   }
 
   return result;
@@ -29,21 +29,21 @@ export function matchRoute(resolvedRoutesConfig, pathMatch) {
  *
  * @param {string} pathMatch
  * @param {string} startPath
- * @param {Array<import('./constructRoutes').Route>} routes
+ * @param {Array<import('./constructRoutes').Route>} children
  */
-function recurseRoutes(pathMatch, startPath, routes) {
+function recurseRoutes(pathMatch, startPath, children) {
   const result = [];
 
-  routes.forEach((route) => {
-    if (route.type === "application") {
-      result.push(route);
+  children.forEach((child) => {
+    if (child.type === "application") {
+      result.push(child);
     } else {
-      const resolvedPath = resolvePath(startPath, route.path);
+      const resolvedPath = resolvePath(startPath, child.path);
 
       if (pathMatch.startsWith(resolvedPath)) {
         result.push({
-          ...route,
-          routes: recurseRoutes(pathMatch, resolvedPath, route.routes),
+          ...child,
+          children: recurseRoutes(pathMatch, resolvedPath, child.children),
         });
       }
     }


Test patch:
diff --git a/test/browser-only/constructLayoutEngine-browser.test.js b/test/browser-only/constructLayoutEngine-browser.test.js
index 37c8674..54658ac 100644
--- a/test/browser-only/constructLayoutEngine-browser.test.js
+++ b/test/browser-only/constructLayoutEngine-browser.test.js
@@ -18,7 +18,7 @@ describe(`constructLayoutEngine browser`, () => {
       containerEl: "body",
       base: "/",
       mode: "history",
-      routes: [{ type: "application", name: "@org-name/header" }],
+      children: [{ type: "application", name: "@org-name/header" }],
     };
 
     layoutEngine = constructLayoutEngine({
@@ -34,7 +34,7 @@ describe(`constructLayoutEngine browser`, () => {
       containerEl: "body",
       base: "/",
       mode: "history",
-      routes: [{ type: "application", name: "@org-name/header" }],
+      children: [{ type: "application", name: "@org-name/header" }],
     };
 
     layoutEngine = constructLayoutEngine({
@@ -61,12 +61,12 @@ describe(`constructLayoutEngine browser`, () => {
       containerEl: "body",
       base: "/",
       mode: "history",
-      routes: [
+      children: [
         { type: "application", name: "@org-name/header" },
         {
           type: "route",
           path: "app1",
-          routes: [{ type: "application", name: "@org-name/app1" }],
+          children: [{ type: "application", name: "@org-name/app1" }],
         },
         { type: "application", name: "@org-name/footer" },
       ],
@@ -179,12 +179,12 @@ describe(`constructLayoutEngine browser`, () => {
       containerEl: "body",
       base: "/",
       mode: "history",
-      routes: [
+      children: [
         { type: "application", name: "@org-name/header" },
         {
           type: "route",
           path: "cart",
-          routes: [
+          children: [
             { type: "application", name: "@org-name/app1" },
             { type: "application", name: "@org-name/app2" },
           ],
@@ -192,7 +192,7 @@ describe(`constructLayoutEngine browser`, () => {
         {
           type: "route",
           path: "settings",
-          routes: [
+          children: [
             { type: "application", name: "@org-name/app2" },
             { type: "application", name: "@org-name/app1" },
           ],
diff --git a/test/constructApplications.test.js b/test/constructApplications.test.js
index 610d084..4aa3828 100644
--- a/test/constructApplications.test.js
+++ b/test/constructApplications.test.js
@@ -6,17 +6,17 @@ describe(`constructApplications`, () => {
       mode: "history",
       base: "/",
       containerEl: "body",
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         {
           type: "route",
           path: "app1",
-          routes: [
+          children: [
             { type: "application", name: "app1", props: { primary: true } },
             {
               type: "route",
               path: "subroute",
-              routes: [
+              children: [
                 { type: "application", name: "subroute", props: { count: 1 } },
               ],
             },
@@ -25,12 +25,12 @@ describe(`constructApplications`, () => {
         {
           type: "route",
           path: "app2",
-          routes: [
+          children: [
             { type: "application", name: "app2" },
             {
               type: "route",
               path: "subroute",
-              routes: [
+              children: [
                 { type: "application", name: "subroute", props: { count: 2 } },
               ],
             },
@@ -108,7 +108,7 @@ describe(`constructApplications`, () => {
       mode: "history",
       base: "/",
       containerEl: "body",
-      routes: [{ type: "application", name: "nav" }],
+      children: [{ type: "application", name: "nav" }],
     };
 
     const loadApp = jest.fn();
diff --git a/test/constructRoutes.test.js b/test/constructRoutes.test.js
index b33b990..9c3d419 100644
--- a/test/constructRoutes.test.js
+++ b/test/constructRoutes.test.js
@@ -27,52 +27,54 @@ describe("constructRoutes", () => {
 
       expect(routes.mode).toBe("history");
       expect(routes.base).toBe("/");
-      expect(routes.routes.length).toBe(5);
+      expect(routes.children.length).toBe(5);
       expect(routes.sourceElement).toBe(routerElement);
 
-      expect(routes.routes[0].type).toBe("application");
-      expect(routes.routes[0].name).toBe("@org/navbar");
-      expect(routes.routes[0].containerEl.nodeName.toLowerCase()).toBe("body");
+      expect(routes.children[0].type).toBe("application");
+      expect(routes.children[0].name).toBe("@org/navbar");
+      expect(routes.children[0].containerEl.nodeName.toLowerCase()).toBe(
+        "body"
+      );
 
-      expect(routes.routes[1].type).toBe("route");
-      expect(routes.routes[1].path).toBe("app1");
-      expect(routes.routes[1].routes.length).toBe(2);
-      expect(routes.routes[1].routes[0].type).toBe("application");
-      expect(routes.routes[1].routes[0].name).toBe("@org/main-sidenav");
+      expect(routes.children[1].type).toBe("route");
+      expect(routes.children[1].path).toBe("app1");
+      expect(routes.children[1].children.length).toBe(2);
+      expect(routes.children[1].children[0].type).toBe("application");
+      expect(routes.children[1].children[0].name).toBe("@org/main-sidenav");
       expect(
-        routes.routes[1].routes[0].containerEl.nodeName.toLowerCase()
+        routes.children[1].children[0].containerEl.nodeName.toLowerCase()
       ).toBe("aside");
-      expect(routes.routes[1].routes[1].type).toBe("application");
-      expect(routes.routes[1].routes[1].name).toBe("@org/app1");
+      expect(routes.children[1].children[1].type).toBe("application");
+      expect(routes.children[1].children[1].name).toBe("@org/app1");
       expect(
-        routes.routes[1].routes[1].containerEl.nodeName.toLowerCase()
+        routes.children[1].children[1].containerEl.nodeName.toLowerCase()
       ).toBe("body");
 
-      expect(routes.routes[2].type).toBe("route");
-      expect(routes.routes[2].path).toBe("app2");
-      expect(routes.routes[2].routes.length).toBe(2);
-      expect(routes.routes[2].routes[0].type).toBe("application");
-      expect(routes.routes[2].routes[0].name).toBe("@org/main-sidenav");
+      expect(routes.children[2].type).toBe("route");
+      expect(routes.children[2].path).toBe("app2");
+      expect(routes.children[2].children.length).toBe(2);
+      expect(routes.children[2].children[0].type).toBe("application");
+      expect(routes.children[2].children[0].name).toBe("@org/main-sidenav");
       expect(
-        routes.routes[2].routes[0].containerEl.nodeName.toLowerCase()
+        routes.children[2].children[0].containerEl.nodeName.toLowerCase()
       ).toBe("aside");
-      expect(routes.routes[2].routes[1].type).toBe("application");
-      expect(routes.routes[2].routes[1].name).toBe("@org/app2");
+      expect(routes.children[2].children[1].type).toBe("application");
+      expect(routes.children[2].children[1].name).toBe("@org/app2");
       expect(
-        routes.routes[2].routes[1].containerEl.nodeName.toLowerCase()
+        routes.children[2].children[1].containerEl.nodeName.toLowerCase()
       ).toBe("body");
 
-      expect(routes.routes[3].type).toBe("route");
-      expect(routes.routes[3].path).toBe("settings");
-      expect(routes.routes[3].routes.length).toBe(1);
-      expect(routes.routes[3].routes[0].type).toBe("application");
-      expect(routes.routes[3].routes[0].name).toBe("@org/settings");
+      expect(routes.children[3].type).toBe("route");
+      expect(routes.children[3].path).toBe("settings");
+      expect(routes.children[3].children.length).toBe(1);
+      expect(routes.children[3].children[0].type).toBe("application");
+      expect(routes.children[3].children[0].name).toBe("@org/settings");
       expect(
-        routes.routes[3].routes[0].containerEl.nodeName.toLowerCase()
+        routes.children[3].children[0].containerEl.nodeName.toLowerCase()
       ).toBe("body");
 
-      expect(routes.routes[4].type).toBe("application");
-      expect(routes.routes[4].name).toBe("@org/footer");
+      expect(routes.children[4].type).toBe("application");
+      expect(routes.children[4].name).toBe("@org/footer");
     });
   });
 
@@ -82,12 +84,12 @@ describe("constructRoutes", () => {
         mode: "history",
         base: "/",
         containerEl: "#selector",
-        routes: [
+        children: [
           { type: "application", name: "@org/navbar" },
           {
             type: "route",
             path: "app1",
-            routes: [
+            children: [
               { type: "application", name: "@org/main-sidenav" },
               { type: "application", name: "@org/app1" },
             ],
@@ -95,7 +97,7 @@ describe("constructRoutes", () => {
           {
             type: "route",
             path: "app2",
-            routes: [
+            children: [
               { type: "application", name: "@org/main-sidenav" },
               { type: "application", name: "@org/app2" },
             ],
@@ -103,7 +105,7 @@ describe("constructRoutes", () => {
           {
             type: "route",
             path: "settings",
-            routes: [{ type: "application", name: "@org/settings" }],
+            children: [{ type: "application", name: "@org/settings" }],
           },
           { type: "application", name: "@org/footer" },
         ],
@@ -134,12 +136,12 @@ describe("constructRoutes", () => {
 
     it(`console.warns if extra properties are provided`, () => {
       constructRoutes({
-        routes: [],
+        children: [],
         irrelevantProperty: "thing",
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        `Invalid routesConfig: received invalid properties 'irrelevantProperty', but valid properties are mode, base, containerEl, routes, disableWarnings`
+        `Invalid routesConfig: received invalid properties 'irrelevantProperty', but valid properties are mode, base, containerEl, children, disableWarnings`
       );
     });
 
@@ -147,18 +149,18 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           mode: "wrong",
-          routes: [],
+          children: [],
         });
       }).toThrowError("mode");
 
       constructRoutes({
         mode: "hash",
-        routes: [],
+        children: [],
       });
 
       constructRoutes({
         mode: "history",
-        routes: [],
+        children: [],
       });
     });
 
@@ -166,14 +168,14 @@ describe("constructRoutes", () => {
       constructRoutes({
         base: "/",
         mode: "history",
-        routes: [],
+        children: [],
       });
 
       expect(() => {
         constructRoutes({
           base: "",
           mode: "history",
-          routes: [],
+          children: [],
         });
       }).toThrowError("non-blank string");
 
@@ -181,7 +183,7 @@ describe("constructRoutes", () => {
         constructRoutes({
           base: "  ",
           mode: "history",
-          routes: [],
+          children: [],
         });
       }).toThrowError("non-blank string");
 
@@ -189,7 +191,7 @@ describe("constructRoutes", () => {
         constructRoutes({
           base: null,
           mode: "history",
-          routes: [],
+          children: [],
         });
       }).toThrowError("non-blank string");
     });
@@ -200,14 +202,14 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           mode: "history",
-          routes: {},
+          children: {},
         });
       }).toThrowError("array");
 
       expect(() => {
         constructRoutes({
           mode: "history",
-          routes: "str",
+          children: "str",
         });
       }).toThrowError("array");
     });
@@ -216,7 +218,7 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           mode: "history",
-          routes: [
+          children: [
             {
               type: "route",
               path: "/",
@@ -224,18 +226,18 @@ describe("constructRoutes", () => {
           ],
         });
       }).toThrowError(
-        `Invalid routesConfig.routes[0].routes: received 'undefined', but expected an array`
+        `Invalid routesConfig.children[0].children: received 'undefined', but expected an array`
       );
     });
 
     it(`checks for valid route objects`, () => {
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "/",
-            routes: [],
+            children: [],
           },
         ],
       });
@@ -243,25 +245,25 @@ describe("constructRoutes", () => {
       console.warn.mockReset();
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "/",
-            routes: [],
+            children: [],
             somethingElse: "value",
           },
         ],
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        `Invalid routesConfig.routes[0]: received invalid properties 'somethingElse', but valid properties are type, path, routes`
+        `Invalid routesConfig.children[0]: received invalid properties 'somethingElse', but valid properties are type, path, children`
       );
     });
 
     it(`checks for valid application objects`, () => {
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "application",
             name: "@org/project",
@@ -272,7 +274,7 @@ describe("constructRoutes", () => {
       console.warn.mockReset();
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "application",
             name: "@org/project",
@@ -282,34 +284,34 @@ describe("constructRoutes", () => {
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        `Invalid routesConfig.routes[0]: received invalid properties 'somethingElse', but valid properties are type, name`
+        `Invalid routesConfig.children[0]: received invalid properties 'somethingElse', but valid properties are type, name`
       );
 
       console.warn.mockReset();
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "application",
             name: "@org/project",
-            routes: [],
+            children: [],
           },
         ],
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        `Invalid routesConfig.routes[0]: received invalid properties 'routes', but valid properties are type, name`
+        `Invalid routesConfig.children[0]: received invalid properties 'children', but valid properties are type, name`
       );
     });
 
     it(`checks subroutes`, () => {
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "thing",
-            routes: [
+            children: [
               {
                 type: "application",
                 name: "navbar",
@@ -322,11 +324,11 @@ describe("constructRoutes", () => {
       expect(console.warn).not.toHaveBeenCalled();
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "thing",
-            routes: [
+            children: [
               {
                 type: "application",
                 name: "navbar",
@@ -338,23 +340,23 @@ describe("constructRoutes", () => {
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        `Invalid routesConfig.routes[0].routes[0]: received invalid properties 'somethingElse', but valid properties are type, name`
+        `Invalid routesConfig.children[0].children[0]: received invalid properties 'somethingElse', but valid properties are type, name`
       );
     });
 
     it(`checks all routes when there are multiple`, () => {
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "/",
-            routes: [],
+            children: [],
           },
           {
             type: "route",
             path: "/app1",
-            routes: [],
+            children: [],
           },
         ],
       });
@@ -362,23 +364,23 @@ describe("constructRoutes", () => {
       expect(console.warn).not.toHaveBeenCalled();
       constructRoutes({
         mode: "history",
-        routes: [
+        children: [
           {
             type: "route",
             path: "/",
-            routes: [],
+            children: [],
           },
           {
             type: "route",
             path: "/app1",
-            routes: [],
+            children: [],
             irrelevantProperty: "thing",
           },
         ],
       });
       expect(console.warn).toHaveBeenCalled();
       expect(console.warn.mock.calls[0][0].message).toEqual(
-        "Invalid routesConfig.routes[1]: received invalid properties 'irrelevantProperty', but valid properties are type, path, routes"
+        "Invalid routesConfig.children[1]: received invalid properties 'irrelevantProperty', but valid properties are type, path, children"
       );
     });
 
@@ -386,7 +388,7 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           containerEl: null,
-          routes: [],
+          children: [],
         });
       }).toThrowError(
         "Invalid routesConfig.containerEl: received null but expected either non-blank string or HTMLElement"
@@ -395,7 +397,7 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           containerEl: [],
-          routes: [],
+          children: [],
         });
       }).toThrowError(
         "Invalid routesConfig.containerEl: received  but expected either non-blank string or HTMLElement"
@@ -404,7 +406,7 @@ describe("constructRoutes", () => {
       expect(() => {
         constructRoutes({
           containerEl: 2342,
-          routes: [],
+          children: [],
         });
       }).toThrowError(
         "Invalid routesConfig.containerEl: received 2342 but expected either non-blank string or HTMLElement"
@@ -414,7 +416,7 @@ describe("constructRoutes", () => {
     it(`allows a string containerEl`, () => {
       constructRoutes({
         containerEl: "asdf",
-        routes: [],
+        children: [],
       });
     });
 
@@ -422,7 +424,7 @@ describe("constructRoutes", () => {
       it("allows an HTMLElement containerEl", () => {
         constructRoutes({
           containerEl: document.createElement("div"),
-          routes: [],
+          children: [],
         });
       });
     }
@@ -434,13 +436,13 @@ describe("constructRoutes", () => {
         constructRoutes({
           containerEl: "body",
           mode: "history",
-          routes: [{ type: "application", name: "nav" }],
+          children: [{ type: "application", name: "nav" }],
         })
       ).toEqual({
         base: "/",
         containerEl: "body",
         mode: "history",
-        routes: [{ type: "application", name: "nav" }],
+        children: [{ type: "application", name: "nav" }],
       });
     });
 
@@ -449,13 +451,13 @@ describe("constructRoutes", () => {
         constructRoutes({
           containerEl: "body",
           base: "/",
-          routes: [{ type: "application", name: "nav" }],
+          children: [{ type: "application", name: "nav" }],
         })
       ).toEqual({
         base: "/",
         containerEl: "body",
         mode: "history",
-        routes: [{ type: "application", name: "nav" }],
+        children: [{ type: "application", name: "nav" }],
       });
     });
 
@@ -464,13 +466,13 @@ describe("constructRoutes", () => {
         constructRoutes({
           base: "/",
           mode: "history",
-          routes: [{ type: "application", name: "nav" }],
+          children: [{ type: "application", name: "nav" }],
         })
       ).toEqual({
         base: "/",
         containerEl: "body",
         mode: "history",
-        routes: [{ type: "application", name: "nav" }],
+        children: [{ type: "application", name: "nav" }],
       });
     });
   });
diff --git a/test/matchRoute.test.js b/test/matchRoute.test.js
index 8bf86ed..f8bdf45 100644
--- a/test/matchRoute.test.js
+++ b/test/matchRoute.test.js
@@ -8,29 +8,29 @@ describe(`matchRoute`, () => {
       mode: "history",
       base: "/",
       containerEl: "body",
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         {
           type: "route",
           path: "app1",
-          routes: [
+          children: [
             { type: "application", name: "app1" },
             {
               type: "route",
               path: "subroute",
-              routes: [{ type: "application", name: "subroute" }],
+              children: [{ type: "application", name: "subroute" }],
             },
           ],
         },
         {
           type: "route",
           path: "app2",
-          routes: [
+          children: [
             { type: "application", name: "app2" },
             {
               type: "route",
               path: "subroute",
-              routes: [{ type: "application", name: "subroute" }],
+              children: [{ type: "application", name: "subroute" }],
             },
           ],
         },
@@ -42,7 +42,7 @@ describe(`matchRoute`, () => {
   it(`returns a filtered routes array`, () => {
     expect(matchRoute(routesConfig, "/")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         { type: "application", name: "footer" },
       ],
@@ -52,12 +52,12 @@ describe(`matchRoute`, () => {
   it(`matches nested routes`, () => {
     expect(matchRoute(routesConfig, "/app1")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         {
           type: "route",
           path: "app1",
-          routes: [{ type: "application", name: "app1" }],
+          children: [{ type: "application", name: "app1" }],
         },
         { type: "application", name: "footer" },
       ],
@@ -65,12 +65,12 @@ describe(`matchRoute`, () => {
 
     expect(matchRoute(routesConfig, "/app2")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         {
           type: "route",
           path: "app2",
-          routes: [{ type: "application", name: "app2" }],
+          children: [{ type: "application", name: "app2" }],
         },
         { type: "application", name: "footer" },
       ],
@@ -80,17 +80,17 @@ describe(`matchRoute`, () => {
   it(`matches deeply nested routes`, () => {
     expect(matchRoute(routesConfig, "/app1/subroute")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         {
           type: "route",
           path: "app1",
-          routes: [
+          children: [
             { type: "application", name: "app1" },
             {
               type: "route",
               path: "subroute",
-              routes: [{ type: "application", name: "subroute" }],
+              children: [{ type: "application", name: "subroute" }],
             },
           ],
         },
@@ -104,12 +104,12 @@ describe(`matchRoute`, () => {
 
     expect(matchRoute(routesConfig, "/")).toEqual({
       ...routesConfig,
-      routes: [],
+      children: [],
     });
 
     expect(matchRoute(routesConfig, "/base/")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         { type: "application", name: "footer" },
       ],
@@ -117,7 +117,7 @@ describe(`matchRoute`, () => {
 
     expect(matchRoute(routesConfig, "/base")).toEqual({
       ...routesConfig,
-      routes: [
+      children: [
         { type: "application", name: "nav" },
         { type: "application", name: "footer" },
       ],
diff --git a/test/single-spa-layout.test-d.ts b/test/single-spa-layout.test-d.ts
index 5eb3983..2459498 100644
--- a/test/single-spa-layout.test-d.ts
+++ b/test/single-spa-layout.test-d.ts
@@ -23,11 +23,11 @@ expectError(constructRoutes([]));
 expectError(constructRoutes({}));
 
 const routes = constructRoutes({
-  routes: [
+  children: [
     {
       type: "route",
       path: "/app1",
-      routes: [{ type: "application", name: "app1" }],
+      children: [{ type: "application", name: "app1" }],
     },
   ],
 });
@@ -48,7 +48,9 @@ expectType<import("../src/constructRoutes").ContainerEl>(
   matchedRoutes.containerEl
 );
 expectType<string>(matchedRoutes.mode);
-expectType<Array<import("../src/constructRoutes").Route>>(matchedRoutes.routes);
+expectType<Array<import("../src/constructRoutes").RouteChild>>(
+  matchedRoutes.children
+);
 
 // test constructApplication
 const applications = constructApplications({