@grasp-labs/ds-microfrontends-integration
v1.1.2
Published
A React library for integrating microfrontend applications. Built with TypeScript, Vite, and Tailwind CSS.
Readme
@grasp-labs/ds-microfrontends-integration
A React library for integrating microfrontend applications. Built with TypeScript, Vite, and Tailwind CSS.
Installation
npm install @grasp-labs/ds-microfrontends-integrationComponents
Vault
Components for managing secrets with JSON Schema-based forms.
Vault Usage
import {
LanguageProvider,
VaultInput,
VaultProvider,
VaultSecretDialog,
} from "@grasp-labs/ds-microfrontends-integration";
import "@grasp-labs/ds-microfrontends-integration/styles.css";
const vaultValue = {
secretsList: secrets,
schema: jsonSchema,
generateSecret: async (data) => newSecret,
updateSecret: async (secret) => updatedSecret,
deleteSecret: async (id) => {},
};
<LanguageProvider>
<VaultProvider value={vaultValue}>
<VaultInput name="apiKey" label="API Key" />
<VaultSecretDialog isOpen={isOpen} onClose={handleClose} />
</VaultProvider>
</LanguageProvider>;VaultInput and VaultSecretDialog use built-in translations, so they must be rendered inside LanguageProvider.
Language
import {
LanguageProvider,
useLanguage,
} from "@grasp-labs/ds-microfrontends-integration";
<LanguageProvider>
<App />
</LanguageProvider>;
function MyComponent() {
const { language, setLanguage } = useLanguage();
return (
<button onClick={() => setLanguage(language === "en" ? "no" : "en")}>
Switch language ({language})
</button>
);
}Toast Notifications
Toast notification system for displaying temporary messages.
import {
ToastProvider,
useToast,
} from "@grasp-labs/ds-microfrontends-integration";
<ToastProvider>
<App />
</ToastProvider>;
function MyComponent() {
const { addToast, removeToast, clearToasts } = useToast();
const showSuccess = () => {
addToast({
message: "Operation completed successfully",
variant: "success",
duration: 5000, // optional, defaults to 5000ms
});
};
return <button onClick={showSuccess}>Show Toast</button>;
}Schema Fields
Auto-generated form fields from JSON Schema.
import { SchemaFields } from "@grasp-labs/ds-microfrontends-integration";
<SchemaFields schema={jsonSchema} control={control} errors={errors} />;Groups and User Context
Helpers for auth-aware rendering:
UserProvider/useUserGroupsProvider/useGroupsGroupGuardfor conditional rendering by required groups
Styling
Import the package stylesheet once:
import "@grasp-labs/ds-microfrontends-integration/styles.css";It includes the required styles from @grasp-labs/ds-react-components.
Microfrontend Configuration (/mf-common)
The platform uses a host / remote architecture powered by Module Federation. A central host application dynamically discovers and mounts independent microfrontend remotes at runtime. For this to work, every remote must follow a shared contract — exposing the same entry points, using compatible shared dependencies, and providing a navigation config so the host can build its sidebar and routing.
mf-common enforces this contract. It provides a pre-configured Vite plugin, shared dependency definitions, and type-safe navigation primitives so that each remote is wired up correctly with minimal boilerplate.
The Contract
Every microfrontend must expose two modules:
| Expose key | Default path | What the host expects |
| ---------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------- |
| "." | "./src/App" | A React component (not a full app with ReactDOM.render). The host mounts it inside its own router |
| "./navigationConfig" | "./src/navigationConfig" | A ComposableNavigationConfig object. The host reads it to build sidebar entries and route definitions |
Navigation Item Types
Each entry in the navigation config is a NavigationItem — either a route or a category:
| Type | Description |
| ---------- | -------------------------------------------------------------------------- |
| visible | A route that appears in the sidebar (default when type is omitted) |
| hidden | A route that is routable but does not appear in the sidebar |
| category | A non-routable group with children — used to create nested sidebar menus |
Every item has a label (display fallback), an optional labelKey (i18n key in the navigation namespace, kept for backward compatibility), an optional translations dictionary, and an icon.
Available Utilities
Build-time (@grasp-labs/ds-microfrontends-integration/mf-common):
dsFederation(name, overrides?)— Vite plugin that wraps Module Federation with the standard configcreateModuleFederationConfig(name, overrides?)— generates the raw Module Federation options if you need more controlcreateMicrofrontendsBase(name)— returns the deployment base path (microfrontends/<name>/), used to set Vite'sbasein productionCOMMON_SHARED_DEPS— shared dependency definitions (React, React Router, this package) configured as singletons- Types:
MicrofrontendExposes
Client-side (@grasp-labs/ds-microfrontends-integration):
defineNavigation(config)— defines a navigation config and extracts its page routes in one step, returning{ navigationConfig, pageRoutes }extractPaths(config)— recursively flattens a navigation config into a type-safe{ KEY: path }map- Types:
RouteConfig,CategoryConfig,NavigationItem,ComposableNavigationConfig
Vite Setup
// vite.config.ts
import {
createMicrofrontendsBase,
dsFederation,
} from "@grasp-labs/ds-microfrontends-integration/mf-common";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { name } from "./package.json";
const MICROFRONTENDS_BASE = createMicrofrontendsBase(name);
export default defineConfig(({ mode }) => ({
base: mode === "production" ? MICROFRONTENDS_BASE : "/",
plugins: [react(), dsFederation(name)],
}));App Component
Your src/App.tsx should export a React component with <Routes>, not render it — the host handles mounting:
// src/App.tsx
import { Routes, Route } from "react-router";
import { HomePage } from "./layouts/HomePage";
import { SettingsPage } from "./layouts/SettingsPage";
import { InternalPage } from "./layouts/InternalPage";
function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/settings" element={<SettingsPage />} />
<Route path="/internal" element={<InternalPage />} />
</Routes>
);
}
export default App;Navigation Configuration
Use defineNavigation to define your navigation config and extract route paths in one step:
// src/navigationConfig.ts
import { defineNavigation } from "@grasp-labs/ds-microfrontends-integration";
const { navigationConfig, pageRoutes: PageRoutes } = defineNavigation({
HOME: {
label: "Home",
path: "/",
icon: "database",
type: "visible",
},
SETTINGS: {
label: "Settings",
path: "/settings",
icon: "cogWheel",
type: "visible",
},
INTERNAL: {
label: "Internal Page",
path: "/internal",
icon: "cogWheel",
type: "hidden",
},
});
export { PageRoutes };
// PageRoutes.HOME === "/"
// PageRoutes.SETTINGS === "/settings"
// PageRoutes.INTERNAL === "/internal"
export default navigationConfig;For nested configs with categories, route paths are recursively flattened into a single map.
Shared Dependencies
Your microfrontend project must install compatible versions of these shared dependencies. Compatible versions are those that match the version ranges specified in this package's COMMON_SHARED_DEPS configuration:
| Dependency | Purpose |
| ------------------------------------------- | ------------------------------------------------------------------------------------ |
| react | UI library — singleton ensures one React instance across all microfrontends |
| react-dom | React DOM renderer — must match React version |
| react-router | Routing library — singleton required for React context to work across microfrontends |
| @grasp-labs/ds-microfrontends-integration | This package — singleton required for React context to work across microfrontends |
These dependencies are configured as singletons to prevent multiple instances and ensure compatibility across the microfrontend architecture.
Development
Prerequisites: Node.js >= 22
npm installDev auth middleware
devAuthMiddleware provides an optional login page for local development and injects Authorization: Bearer <token> for backend calls when a token is available. Mount it before anything that proxies to your APIs so outbound requests receive the token automatically.
import express from "express";
import { devAuthMiddleware } from "@grasp-labs/ds-microfrontends-integration/dev";
const app = express();
app.use(devAuthMiddleware());
// Or with custom options:
app.use(
devAuthMiddleware({
loginPagePath: "/__login", // Path for the login page
afterLoginRedirectPath: "/", // Where to redirect after login
authServerLoginUrl: "https://auth-dev.grasp-daas.com/rest-auth/login/", // Auth server endpoint
}),
);The login page is available at /__login (configurable via loginPagePath). Navigate there manually when you need to authenticate. Alternatively, set DEV_AUTH_TOKEN (env var or .env file) before starting the server to skip the login form entirely.
After a successful login, the middleware redirects to process.env.VITE_BASE_PATH when set, otherwise / (override via afterLoginRedirectPath if needed).
Scripts
npm run build- Build the librarynpm run dev- Build in watch modenpm run storybook- Run Storybook dev servernpm run build-storybook- Build Storybook static filesnpm run lint- Run ESLintnpm run lint:fix- Fix ESLint errorsnpm run format- Format code with Prettiernpm run format:check- Check code formattingnpm test- Run testsnpm run test:watch- Run tests in watch modenpm run test:coverage- Generate test coverage reportnpm run tsc- Run TypeScript type-checkingnpm run check- Runtsc, lint, format check, and tests
Project Structure
src/
├── components/ # React components (vault, language, schema fields, toast, groups, user)
├── hooks/ # Shared hook exports
├── dev/ # Dev auth middleware entrypoint
├── lib/ # JSON schema utilities and shared logic
├── types/ # TypeScript type definitions
├── utils/ # Shared helper functions
├── mf-common.ts # Build-time microfrontend configuration (Vite plugin, Module Federation)
└── index.ts # Main entry pointContributing
- Create a feature branch
- Ensure
npm run checkpasses - Create a pull request
