React frontend for a developer discovery and networking platform. Swipe-based profile browsing, real-time chat, online presence indicators, and live connection request notifications.
Live: linkdev.online · Backend: devlink-backend
| Framework | React 19 + Vite |
| Styling | Tailwind CSS v4 |
| State | Redux Toolkit |
| Routing | React Router v7 |
| Real-time | Socket.io client |
| HTTP | Axios (interceptor + cookie auth) |
| Payments | Razorpay |
New users complete a four-step flow: register → verify email → login → onboarding. After login, the server issues access (15m) + refresh (30d) tokens in httpOnly cookies. The Axios interceptor handles silent token refresh automatically — on a 401, it calls /auth/refresh and retries the original request once before redirecting to /login.
Swipe feed — draggable card stack with green/red overlay on drag. Fetches 5 profiles at a time, auto-fetches more when ≤ 2 cards remain. Skill-based filtering via ?skills=React,Node.js. Pagination uses refs (pageRef, isFetchingRef, hasMoreRef) to avoid stale-closure re-render loops.
Axios interceptor — all API calls use a shared api.js instance. On a 401 response, the interceptor automatically attempts a token refresh via /auth/refresh and retries the original request once. If refresh fails, redirects to /login. Prevents manual token handling in every component.
Offline / server error handling — AuthLoader distinguishes between auth failure (401, handled by interceptor) and network failure (no response). Shows a "Can't reach the server" screen with a retry button on network errors instead of silently failing or redirecting to login.
Real-time notifications — Socket.io listener in Layout.jsx dispatches to Redux on newNotification. NavBar badge counts are derived via useMemo and clear automatically when the user visits the relevant page.
Online presence — on socket register, the server returns an onlineList snapshot so the UI is accurate immediately. Green dot in ChatInbox, "Active" badge in Connections grid.
Connection requests — send, accept, reject, withdraw. Accepted requests fire a request_accepted notification to the original sender.
Real-time chat — Socket.io room per conversation pair (deterministic hash). Messages persisted to MongoDB and fetched on mount.
Email verification — /verify-email page handles the token from query params. On success, redirects to /app with ?verified=true; AuthLoader detects the flag, shows a toast, and clears the param.
Onboarding — 4-step full-page flow on first login for new users. Skill chips, custom gender pills (no native <select>), GitHub username. Completion tracked via onboardingComplete on the user document.
Premium — Razorpay order creation and client-side payment verification. Membership badge displayed on profile cards and profile pages based on membershipType from user state.
GitHub integration — fetches api.github.com/users/:username on profile pages. Shows repos, followers, bio.
| Slice | What it holds |
|---|---|
userSlice |
Logged-in user |
feedSlice |
Feed profiles (initialState: [], never null) |
connectionSlice |
Accepted connections |
requestSlice |
Received requests |
skillsSlice |
Predefined skills + loaded flag |
notificationSlice |
In-session notifications (badge source) |
onlineSlice |
Array of currently-online user IDs |
Layout mounts (user logged in)
└── socket.emit("register", user._id)
├── server → "onlineList" → dispatch(setOnlineList)
└── server → "userOnline" → dispatch(setOnline)
socket.on("userOffline") → dispatch(setOffline)
socket.on("newNotification")
├── type "message" → dispatch(addNotification) + toast
├── type "request" → dispatch(addNotification) + toast
└── type "request_accepted" → dispatch(addNotification) + toast
User visits /app/messages → dispatch(clearByType("message"))
User visits /app/requests → dispatch(clearByType("request"))
| Path | Page |
|---|---|
/ |
Landing |
/login |
Login / signup |
/verify-email |
Email verification (token from query param) |
/app |
Feed |
/app/onboarding |
Onboarding (4 steps) |
/app/connections |
Connections grid |
/app/requests |
Requests (tab persisted in URL) |
/app/messages |
Chat inbox |
/app/messages/:targetUserId |
Conversation |
/app/profile |
Own profile + edit |
/app/profile/:userId |
Other user's profile |
/app/premium |
Pricing + payment |
git clone https://github.com/Dhruv-Raichand/devlink-frontend.git
cd devlink-frontend && npm install
cp .env.example .env
npm run devVITE_BASE_URL=http://localhost:3000npm run dev # Vite dev server
npm run build # Production build
npm run lint # ESLintDhruv Raichand · DevLink © 2026


