A React frontend application that allows users to upload GitHub projects and offers a Q&A chat interface.
Our frontend uses a modern, lightweight stack optimized for rapid development and type safety:
- React 19 - Component-based UI framework for building interactive interfaces.
- TypeScript - Adds static typing to catch errors early and improve code reliability.
- Vite - Lightning-fast build tool with instant hot module replacement.
- ESLint - Code linting with type-aware rules for TypeScript.
This combination provides excellent developer experience with fast builds, strong typing for our API integrations, and a minimal setup that scales well. Perfect for building forms, chat interfaces, and handling API responses from our multi-service backend.
# Install dependencies
npm install
# Start development server
npm run dev
# Lint code
npm run lint
# Build for production
npm run build
# Preview production build
npm run previewsrc/
├── App.tsx # Main application component
├── index.css # Global styles
├── main.tsx # Application entry point
├── types/ # Internal and external types.
└── components/ # UI components.
- Using npm (local development):
npm run dev- Using Docker Compose:
docker compose build frontend
docker compose up -d --wait frontendThe production container serves the built frontend using NGINX, configured in frontend/nginx.conf:
location /serves static files and falls back toindex.htmlso client-side routes work.location /api/proxies requests to the backend service URL configured at runtime viaBACKEND_URL.
This means the browser only talks to a single origin (the frontend origin), and API calls go through /api/*.
The frontend uses two backend-related variables on purpose:
-
VITE_BACKEND_API_URL(build-time, browser-side) — used by the React app to buildfetch()URLs. -
Because it is a
VITE_*variable, it is baked into the JS bundle when you runnpm run build. -
In the production Docker image we set it to
/apiso the browser calls the same origin (no CORS). -
BACKEND_URL(runtime, container-side) — used by NGINX to proxy/api/*to the real backend. -
This is injected at container runtime (Docker Compose / Railway env vars).
-
Example (Docker Compose):
BACKEND_URL=http://backend:8080 -
Example (Railway):
BACKEND_URL=https://<your-backend>.up.railway.app
Rule of thumb:
- Browser talks to
/api/...(controlled byVITE_BACKEND_API_URL=/api). - NGINX decides where
/api/...goes (controlled byBACKEND_URL=...).
The frontend container listens on the port given by PORT (default 5173), which is especially important on PaaS platforms like Railway that inject PORT at runtime.