A modern React frontend client for FastAPI applications with WebSocket and HTTP support, built with Bun and Vite.
- Keycloak Authentication: Secure login with Keycloak SSO, automatic token refresh, and role-based access control
- WebSocket Client: Real-time bidirectional communication with automatic reconnection and authentication
- HTTP Client: Type-safe HTTP client with automatic token injection and support for all REST methods
- Modern Stack: React 19, TypeScript, Vite, and Bun
- Responsive UI: Beautiful, responsive interface with real-time status indicators
- Developer Friendly: Hot module replacement, TypeScript support, and clean code structure
- Bun (latest version)
- A FastAPI backend server running on
http://localhost:8000 - Keycloak server running on
http://localhost:8080(configured with realm and client)
Install dependencies:
bun installStart the development server:
bun run devThe application will be available at http://localhost:3000.
bun run buildPreview the production build:
bun run previewCreate a .env file based on .env.example:
cp .env.example .envAvailable environment variables:
VITE_API_URL: Base URL for HTTP API requests (default:/api)VITE_WS_URL: WebSocket server URL (default:ws://localhost:8000/ws)VITE_KEYCLOAK_BASE_URL: Keycloak server URL (default:http://localhost:8080)VITE_KEYCLOAK_REALM: Keycloak realm name (default:HW-App)VITE_KEYCLOAK_CLIENT_ID: Keycloak client ID (default:auth-hw-frontend)
src/
├── components/ # React components
│ ├── auth/ # Authentication components
│ │ ├── LoginPage.tsx # Login page component
│ │ ├── LoginPage.css # Login page styles
│ │ └── ProtectedRoute.tsx # Route protection wrapper
│ ├── Header.tsx # App header with user info
│ └── Header.css # Header styles
├── context/ # React context providers
│ └── AuthContext.tsx # Authentication state management
├── hooks/ # Custom React hooks
│ └── useWebSocket.ts # WebSocket client hook
├── types/ # TypeScript type definitions
│ └── auth.ts # Authentication types
├── utils/ # Utility functions
│ ├── httpClient.ts # HTTP client with auth
│ └── authClient.ts # Keycloak authentication client
├── App.tsx # Main application component
├── App.css # Application styles
├── main.tsx # Application entry point
└── vite-env.d.ts # Vite environment types
The application uses Keycloak for authentication:
- On first load, you'll be presented with a login page
- Enter your Keycloak username and password
- Upon successful login, you'll be redirected to the main application
- Your access token is automatically refreshed before expiration
- Tokens are stored securely in localStorage
- Click "Logout" in the header to end your session
Authentication Features:
- Automatic token refresh (30 seconds before expiration)
- Secure token storage
- Role-based access control (RBAC) support
- WebSocket authentication via query parameter
- HTTP client automatic Bearer token injection
The application provides a real-time WebSocket interface with automatic authentication:
- Enter your WebSocket URL (default:
ws://localhost:8000/ws) - The client automatically connects with your access token and shows connection status
- Send messages through the input field
- Receive and display messages in real-time
- Automatic reconnection on connection loss or token refresh
Test HTTP endpoints with automatic authentication:
- Enter your API endpoint (e.g.,
/health,/api/users) - Click "Send Request" to make a GET request (Bearer token automatically added)
- View the formatted JSON response
import { useAuth } from './context/AuthContext';
const { user, isAuthenticated, login, logout, accessToken } = useAuth();
// Login
await login('username', 'password');
// Access user info
console.log(user.username, user.roles);
// Logout
await logout();import { useWebSocket } from './hooks/useWebSocket';
const { isConnected, sendMessage, lastMessage } = useWebSocket({
url: 'ws://localhost:8000/ws',
onMessage: (data) => console.log('Received:', data),
reconnect: true,
});import { httpClient } from './utils/httpClient';
// Set auth token (automatically done by App component)
httpClient.setAuthToken(accessToken);
// GET request
const data = await httpClient.get('/api/users');
// POST request
const result = await httpClient.post('/api/users', { name: 'John' });import { ProtectedRoute } from './components/auth/ProtectedRoute';
// Basic protection (requires authentication)
<ProtectedRoute>
<YourComponent />
</ProtectedRoute>
// Role-based protection
<ProtectedRoute requiredRoles={['admin', 'user']}>
<AdminComponent />
</ProtectedRoute>Here's a simple FastAPI backend to use with this client:
from fastapi import FastAPI, WebSocket
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
async def health():
return {"status": "healthy"}
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Echo: {data}")
except:
passType checking:
bun run lint- React 19: Latest React with concurrent features
- TypeScript: Type-safe development
- Vite: Fast build tool and dev server
- Bun: Fast JavaScript runtime and package manager
- Keycloak: Enterprise-grade authentication and authorization
- WebSocket API: Native browser WebSocket support with authentication
MIT