diff --git a/frontend/index.html b/frontend/index.html
index b13d84f2..8cb7c97a 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -24,7 +24,7 @@ limitations under the License.
matrix-authentication-service
-
+
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c9ca823b..1141cd76 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -11,6 +11,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^14.1.0",
+ "react-router-dom": "^6.4.3",
"relay-runtime": "^14.1.0"
},
"devDependencies": {
@@ -2648,6 +2649,14 @@
"node": ">=10.12.0"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
+ "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@repeaterjs/repeater": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz",
@@ -6983,6 +6992,36 @@
"react": "^16.9.0 || ^17 || ^18"
}
},
+ "node_modules/react-router": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
+ "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
+ "dependencies": {
+ "@remix-run/router": "1.0.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
+ "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
+ "dependencies": {
+ "@remix-run/router": "1.0.3",
+ "react-router": "6.4.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -9927,6 +9966,11 @@
"webcrypto-core": "^1.7.4"
}
},
+ "@remix-run/router": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz",
+ "integrity": "sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q=="
+ },
"@repeaterjs/repeater": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz",
@@ -12972,6 +13016,23 @@
"relay-runtime": "14.1.0"
}
},
+ "react-router": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.3.tgz",
+ "integrity": "sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==",
+ "requires": {
+ "@remix-run/router": "1.0.3"
+ }
+ },
+ "react-router-dom": {
+ "version": "6.4.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.3.tgz",
+ "integrity": "sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==",
+ "requires": {
+ "@remix-run/router": "1.0.3",
+ "react-router": "6.4.3"
+ }
+ },
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index ebcc56f7..160a08e3 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -15,6 +15,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-relay": "^14.1.0",
+ "react-router-dom": "^6.4.3",
"relay-runtime": "^14.1.0"
},
"devDependencies": {
diff --git a/frontend/src/Router.tsx b/frontend/src/Router.tsx
new file mode 100644
index 00000000..f62b6bbd
--- /dev/null
+++ b/frontend/src/Router.tsx
@@ -0,0 +1,48 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { lazy, Suspense } from "react";
+import { createHashRouter, Outlet, RouterProvider } from "react-router-dom";
+
+import Layout from "./components/Layout";
+import LoadingSpinner from "./components/LoadingSpinner";
+
+const Home = lazy(() => import("./pages/Home"));
+
+export const router = createHashRouter([
+ {
+ path: "/",
+ element: (
+
+ }>
+
+
+
+ ),
+ children: [
+ {
+ index: true,
+ element: ,
+ },
+ {
+ path: "dumb",
+ element: <>Hello from another dumb page.>,
+ },
+ ],
+ },
+]);
+
+const Router = () => ;
+
+export default Router;
diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx
new file mode 100644
index 00000000..467fb380
--- /dev/null
+++ b/frontend/src/components/Layout.tsx
@@ -0,0 +1,31 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import NavBar from "./NavBar";
+import NavItem from "./NavItem";
+
+const Layout: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
+ return (
+
+
+ Home
+ Dumb
+
+
+ {children}
+
+ );
+};
+
+export default Layout;
diff --git a/frontend/src/components/LoadingScreen.tsx b/frontend/src/components/LoadingScreen.tsx
new file mode 100644
index 00000000..6071f39a
--- /dev/null
+++ b/frontend/src/components/LoadingScreen.tsx
@@ -0,0 +1,23 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import LoadingSpinner from "./LoadingSpinner";
+
+const LoadingScreen: React.FC = () => (
+
+
+
+);
+
+export default LoadingScreen;
diff --git a/frontend/src/components/LoadingSpinner.tsx b/frontend/src/components/LoadingSpinner.tsx
new file mode 100644
index 00000000..c7472510
--- /dev/null
+++ b/frontend/src/components/LoadingSpinner.tsx
@@ -0,0 +1,34 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React from "react";
+
+const LoadingSpinner: React.FC = () => (
+
+
+ Loading...
+
+);
+
+export default LoadingSpinner;
diff --git a/frontend/src/components/NavBar.tsx b/frontend/src/components/NavBar.tsx
new file mode 100644
index 00000000..3184f2b9
--- /dev/null
+++ b/frontend/src/components/NavBar.tsx
@@ -0,0 +1,24 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const NavBar: React.FC<{
+ className: string;
+ children: React.ReactNode;
+}> = ({ className, children }) => (
+
+);
+
+export default NavBar;
diff --git a/frontend/src/components/NavItem.tsx b/frontend/src/components/NavItem.tsx
new file mode 100644
index 00000000..acea1b13
--- /dev/null
+++ b/frontend/src/components/NavItem.tsx
@@ -0,0 +1,36 @@
+// Copyright 2022 The Matrix.org Foundation C.I.C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { NavLink } from "react-router-dom";
+
+const NavItem: React.FC<{ to: string; children: React.ReactNode }> = ({
+ to,
+ children,
+}) => (
+