diff --git a/.changeset/forty-singers-look.md b/.changeset/forty-singers-look.md
new file mode 100644
index 0000000000..1b3919e214
--- /dev/null
+++ b/.changeset/forty-singers-look.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-app-api': patch
+---
+
+Fix a bug in `FlatRoutes` that prevented outlets from working with the root route, as well as matching root routes too broadly.
diff --git a/packages/core-app-api/src/routing/FlatRoutes.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.test.tsx
index a73534a272..d5201a6f57 100644
--- a/packages/core-app-api/src/routing/FlatRoutes.test.tsx
+++ b/packages/core-app-api/src/routing/FlatRoutes.test.tsx
@@ -100,7 +100,6 @@ describe('FlatRoutes', () => {
return <>Outlet: {useOutlet()}>;
};
- // The '/*' suffixes here are intentional and will be ignored by FlatRoutes
const routes = (
<>
}>
@@ -112,11 +111,15 @@ describe('FlatRoutes', () => {
}>
b
+ }>
+ c
+
>
);
const renderRoute = makeRouteRenderer({routes});
expect(renderRoute('/a').getByText('Outlet: a')).toBeInTheDocument();
expect(renderRoute('/a/b').getByText('Outlet: a-b')).toBeInTheDocument();
expect(renderRoute('/b').getByText('Outlet: b')).toBeInTheDocument();
+ expect(renderRoute('/').getByText('Outlet: c')).toBeInTheDocument();
});
});
diff --git a/packages/core-app-api/src/routing/FlatRoutes.tsx b/packages/core-app-api/src/routing/FlatRoutes.tsx
index 6ba82203fd..315ec91cdb 100644
--- a/packages/core-app-api/src/routing/FlatRoutes.tsx
+++ b/packages/core-app-api/src/routing/FlatRoutes.tsx
@@ -49,8 +49,10 @@ export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => {
element: child,
children: child.props.children
? [
+ // These are the children of each route, which we all add in under a catch-all
+ // subroute in order to make them available to `useOutlet`
{
- path: '/*',
+ path: path === '/' ? '/' : '/*', // The root path must require an exact match
element: child.props.children,
},
]