Add routing foundation to compliance-portal

Wire up react-router with a root layout route and an index home page,
following the single-arborescence conventions: pages live under pages/,
routes are built from AppRoute via routeFromAppRoute, and route bundles
load lazily behind a Suspense fallback.

Add the @probo/routes and @probo/react-lazy workspace dependencies that
the route setup relies on.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-22 19:16:17 +02:00
parent eabf46c5cb
commit 023fb70a58
7 changed files with 109 additions and 5 deletions

View File

@@ -10,6 +10,8 @@
"preview": "vite preview"
},
"dependencies": {
"@probo/react-lazy": "1.0.0",
"@probo/routes": "1.0.0",
"@probo/ui": "1.0.0",
"clsx": "^2.1.1",
"react": "^19.2.7",

View File

@@ -12,10 +12,10 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import { RouterProvider } from "react-router";
import { router } from "#/routes";
export function App() {
return (
<main className="flex min-h-screen items-center justify-center bg-sand-1">
<h1 className="text-6 font-bold text-sand-12">Compliance Portal</h1>
</main>
);
return <RouterProvider router={router} />;
}

View File

@@ -0,0 +1,21 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
export function PageSkeleton() {
return (
<div className="flex min-h-screen items-center justify-center bg-sand-1">
<div className="h-8 w-48 animate-pulse rounded bg-sand-4" />
</div>
);
}

View File

@@ -0,0 +1,21 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
export default function HomePage() {
return (
<main className="flex min-h-screen items-center justify-center">
<h1 className="text-6 font-bold text-sand-12">Compliance Portal</h1>
</main>
);
}

View File

@@ -0,0 +1,23 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import { Outlet } from "react-router";
export default function MainLayout() {
return (
<div className="min-h-screen bg-sand-1">
<Outlet />
</div>
);
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2026 Probo Inc <hello@probo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import { lazy } from "@probo/react-lazy";
import { type AppRoute, routeFromAppRoute } from "@probo/routes";
import { createBrowserRouter } from "react-router";
import { PageSkeleton } from "#/components/skeletons/PageSkeleton";
const routes = [
{
path: "/",
Fallback: PageSkeleton,
Component: lazy(() => import("#/pages/MainLayout")),
children: [
{
index: true,
Component: lazy(() => import("#/pages/HomePage")),
},
],
},
] satisfies AppRoute[];
export const router = createBrowserRouter(routes.map(routeFromAppRoute));

2
package-lock.json generated
View File

@@ -29,6 +29,8 @@
"name": "@probo/compliance-portal",
"version": "0.0.0",
"dependencies": {
"@probo/react-lazy": "1.0.0",
"@probo/routes": "1.0.0",
"@probo/ui": "1.0.0",
"clsx": "^2.1.1",
"react": "^19.2.7",