A modern React application built with Vite that implements user authentication and management.
- Frontend Framework: React 18 with TypeScript
- Build Tool: Vite
- Styling: Tailwind CSS with custom components based on shadcn/ui
- State Management: React Query for server state
- Routing: React Router v6
- HTTP Client: Axios
- Authentication: JWT-based authentication
src/
├── components/ # Reusable UI components
│ ├── ui/ # Base UI components
│ └── ProtectedRoute.tsx # Auth wrapper component
├── lib/ # Utilities and API client
│ ├── api.ts # Axios instance and API endpoints
│ └── utils.ts # Utility functions
├── pages/ # Page components
├── types/ # TypeScript type definitions
└── App.tsx # Main application component
- User authentication (login/register)
- Protected routes with automatic token verification
- Role-based access control (Admin/Client roles)
- User management:
- View all users
- Edit user details (admin only)
- Delete users (admin only)
- Modern UI components
- Type-safe API calls
- QR code generator
- Responsive design
- Ecommerce features
- Admin dashboard
- LLM assistant workspace with dedicated Chat, Generate, and Tools modes
/llmis a landing page that explains when to use each mode and links to/llm/chat,/llm/generate, and/llm/tools.- Chat streams conversations through
qwen3.5:2band can expose the model’s thinking traces on demand. - Generate also targets
qwen3.5:2bbut uses a single-prompt workflow with the same temperature + thinking controls. - Tools is the catalog/Grokipedia playground pinned to
qwen3.5:2b, showing live tool call notices, tool outputs, and the same opt-in thinking control for tool-focused runs. - The Tools mode fetches runtime tool schemas from the backend at
/api/v1/ollama/chat/tools/definitionsand renders an expandable JSON viewer so you see exactly what’s passed to the LLM.
-
Install dependencies:
npm install
-
Start the development server:
npm run dev
The application will be available at http://localhost:8081.
For the containerized training stack, run the same topology used by CI:
docker compose up -dThat builds this frontend into its production nginx image, keeps the backend on the internal Docker network, and publishes a gateway on http://localhost:8081.
The frontend supports one codepath across these runtime shapes:
- local Vite development
- Dockerized Vite development
- lightweight Docker runtime
- full Docker / localstack-style runtime
- server deployment behind a single public origin such as
https://awesome.byst.re
Built frontend assets are expected to run same-origin with the backend gateway. Only Vite development mode talks directly to the backend by default.
The frontend expects the backend business API only under /api/v1/.... There is no old-path fallback for /users/..., /email, /qr/create, /api/ollama/..., or /ws-traffic.
The frontend runtime behavior is controlled by three environment variables:
VITE_API_BASE_URLOptional. Overrides the resolved API origin completely. Use this only when the frontend must call a non-default backend origin.VITE_PASSWORD_RESET_BASE_URLOptional. Controls the absolute reset page URL sent in forgot-password requests. Defaults to${window.location.origin}/reset.VITE_DOCKERDev-only flag. Whentrue, Vite development mode targetshttp://host.docker.internal:4001instead ofhttp://localhost:4001.
Default behavior by profile:
- local Vite dev: API
http://localhost:4001, reset base${window.location.origin}/reset - Dockerized Vite dev: API
http://host.docker.internal:4001whenVITE_DOCKER=true - built Docker/server runtime: API same-origin via
window.location.origin, reset base${window.location.origin}/resetunless overridden
Product image URLs are rendered exactly as provided by the backend. Relative paths like /images/iphone.png are supported and preferred for same-origin deployments.
When this frontend is deployed behind the awesome-localstack gateway, the /images/... path is owned by the gateway and is used for shared static product images mounted from the stack host.
That means:
- frontend-owned branding assets must not live under
/images/... - use a separate public prefix such as
/branding/...for logos, favicons, and similar frontend-only files - if a logo works locally from the frontend container but returns
404behind the gateway, check for a path collision with the gateway’s/images/...alias first
Current convention in this repo:
- product/backend-managed images:
/images/... - frontend branding assets:
/branding/...
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production build./build-multiarch.sh <version>- Build and push the multi-arch frontend image, for example./build-multiarch.sh 3.6.2
This project follows specific guidelines defined in Cursor rules. These rules are located in the .cursor/rules directory:
-
.cursor/rules/project-structure.md- Directory structure
- Component organization
- Styling guidelines
- API integration patterns
- State management
- Code style
-
.cursor/rules/testing.md- Unit and E2E test patterns
- Test file organization
- Testing best practices
- Available test commands
-
.cursor/rules/environment.md- Development environment setup
- Backend services configuration
- Common issues and solutions
- Development workflow
-
.cursor/rules/ai-agent.md- AI agent behavior
- Test execution requirements
- Change validation process
- Error handling procedures
Run https://github.com/slawekradzyminski/test-secure-backend
The backend service runs on http://localhost:4001 and provides:
- API Documentation:
/v3/api-docs - Swagger UI:
/swagger-ui/index.html - H2 Database Console:
/h2-console
Business API calls from this frontend now target:
/api/v1/users/.../api/v1/email/api/v1/qr/create/api/v1/products/.../api/v1/orders/.../api/v1/cart/.../api/v1/traffic/info/api/v1/ollama/.../api/v1/ws-traffic
The frontend now exposes:
/forgot-password– allows anonymous users to request a reset using their username or e-mail. The reset link base URL defaults to${window.location.origin}/resetand can be overridden via the optionalVITE_PASSWORD_RESET_BASE_URLenv variable./reset– consumes the token delivered via e-mail and lets the user pick a new password.
For local development you can retrieve reset links in two ways:
- Local Spring profile – authenticate as an admin, call
DELETE /api/v1/local/email/outboxbefore tests to clear it, then inspectGET /api/v1/local/email/outbox(default:http://localhost:4001/api/v1/local/email/outbox) to grab the latest payload and token. Protected sandbox deployments also requireX-Local-Outbox-Key, sourced by the E2E suite fromLOCAL_EMAIL_OUTBOX_ACCESS_KEY. - Docker/localstack profile – open Mailhog at http://localhost:8025 and copy the reset link from the emulated e-mail.
After successfully resetting a password the app redirects back to /login and displays a toast confirming the update.
Run all checks before submitting changes:
npm run build # Type-check + Vite production build
npm test # Vitest suite
npx playwright test # E2E tests (requires docker compose gateway on :8081 and Keycloak on :8082)Before launching Playwright:
- Run
docker compose up -dfrom this repository. The compose stack builds the frontend nginx image and starts backend, Keycloak, Ollama mock, and the8081gateway. - Wait for the stack with
./scripts/wait-for-backend.sh,./scripts/wait-for-keycloak.sh, and./scripts/wait-for-frontend.sh. - Run
npx playwright test.
Playwright exercises the full stack (e.g., the Tools tab triggers real streaming tool calls), so deterministic results come from the containerized mock service. Backend API calls go through the same gateway origin as the browser: http://localhost:8081/api/....
The SSO Playwright specs exercise two paths:
npx playwright test e2e/tests/sso.spec.ts e2e/tests/sso-fixture.spec.tssso.spec.tsdrives the real browser redirect through Keycloak.sso-fixture.spec.tsobtains a Keycloak ID token over HTTP, exchanges it with the backend, and starts the page with app-issued tokens already in local storage.
CI uses this repository's docker-compose.yml, so the backend image referenced there must already contain the SSO exchange endpoint. After backend changes, publish a new backend image from ../test-secure-backend with ./build-multiarch.sh <version>, then run frontend CI with BACKEND_IMAGE=slawekradzyminski/backend:<version> or update the compose default tag.