Micro UI (Micro Frontends) is an architectural approach that allows us to break down a large frontend into smaller, independently developed, and deployed modules. When combined with Next.js and TypeScript, this approach provides scalability, flexibility, and maintainability.
In this post, we’ll take it a step further by adding authentication using Node.js APIs with session handling, ensuring a secure and seamless user experience across Micro UI modules.
Why Next.js, TypeScript, and Micro UI?
Next.js is an ideal framework for Micro UI because it provides:
- Server-Side Rendering (SSR) & Static Site Generation (SSG)
- API Routes for Backend Integration
- Built-in Support for Authentication and Session Management
TypeScript ensures type safety and maintainability, making it easier to manage independent Micro UI components across teams.
Project Setup for Micro UI with Authentication
We'll structure our project to include a main Next.js app, a User Profile Micro UI module, and a Node.js authentication API.
📂 Project Structure
/micro-ui-app
/apps
/main-app (Next.js application - main frontend)
/user-profile (Micro UI module)
/backend
/auth-service (Node.js API for authentication)
/shared
/components (Reusable UI components)
/utils (Common utility functions)
Step 1: Setting Up Authentication in Node.js (Express API)
First, we’ll create a Node.js API for authentication using Express and session-based authentication.
1.1 Initialize the Backend
mkdir backend/auth-service && cd backend/auth-service
npm init -y
npm install express express-session cors bcryptjs jsonwebtoken dotenv
1.2 Create a Simple Authentication Server
Create a file server.js:
require("dotenv").config();
const express = require("express");
const session = require("express-session");
const cors = require("cors");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const app = express();
app.use(express.json());
app.use(cors({ credentials: true, origin: "http://localhost:3000" }));
app.use(
session({
secret: process.env.SESSION_SECRET || "supersecret",
resave: false,
saveUninitialized: false,
cookie: { secure: false, httpOnly: true },
})
);
const users = [
{ id: 1, username: "john", password: bcrypt.hashSync("password", 10) },
];
app.post("/login", (req, res) => {
const { username, password } = req.body;
const user = users.find((u) => u.username === username);
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(401).json({ message: "Invalid credentials" });
}
req.session.user = { id: user.id, username: user.username };
res.json({ message: "Login successful", user: req.session.user });
});
app.get("/me", (req, res) => {
if (!req.session.user) {
return res.status(401).json({ message: "Not authenticated" });
}
res.json({ user: req.session.user });
});
app.post("/logout", (req, res) => {
req.session.destroy();
res.json({ message: "Logged out" });
});
const PORT = 5000;
app.listen(PORT, () => console.log(`Auth server running on port ${PORT}`));
Step 2: Integrating Authentication in Next.js (Main App)
2.1 Install Dependencies in the Main App
Inside main-app, install necessary packages:
shCopyEdit
cd apps/main-app
npm install axios swr next-auth
2.2 Create an Authentication Context
Inside contexts/AuthContext.tsx:
import React, { createContext, useState, useEffect } from "react";
import axios from "axios";
interface User {
id: number;
username: string;
}
interface AuthContextProps {
user: User | null;
login: (username: string, password: string) => Promise<void>;
logout: () => Promise<void>;
}
export const AuthContext = createContext<AuthContextProps | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
axios.get("http://localhost:5000/me", { withCredentials: true })
.then((res) => setUser(res.data.user))
.catch(() => setUser(null));
}, []);
const login = async (username: string, password: string) => {
await axios.post("http://localhost:5000/login", { username, password }, { withCredentials: true });
setUser({ id: 1, username });
};
const logout = async () => {
await axios.post("http://localhost:5000/logout", {}, { withCredentials: true });
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
2.3 Create Login Page
Inside pages/login.tsx:
import { useState, useContext } from "react";
import { AuthContext } from "../contexts/AuthContext";
const LoginPage = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const auth = useContext(AuthContext);
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
if (auth) await auth.login(username, password);
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleLogin}>
<input value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" />
<button type="submit">Login</button>
</form>
</div>
);
};
export default LoginPage;
Step 3: Protecting Micro UI Components
Now, let’s secure the User Profile Micro UI so it only displays data for authenticated users.
Modify user-profile/components/UserProfile.tsx:
import { useContext } from "react";
import { AuthContext } from "../../contexts/AuthContext";
const UserProfile = () => {
const auth = useContext(AuthContext);
if (!auth?.user) {
return <p>Please login to view your profile.</p>;
}
return (
<div className="p-4 border rounded">
<h2 className="text-lg font-bold">{auth.user.username}</h2>
</div>
);
};
export default UserProfile;
Conclusion
By integrating session-based authentication with Node.js and Next.js, we ensure that:
✅ Users remain logged in across different Micro UI modules.
✅ Authentication state is shared securely between frontend and backend.
✅ Micro UI components only display data for authenticated users.
Next Steps
- Deploy the Node.js authentication API on AWS, Vercel, or Digital Ocean.
- Use JWT instead of sessions for better scalability.
- Implement role-based access control (RBAC) in Micro UI components.
Would you like a guide on deploying this Micro UI system? Let me know in the comments!