⚡ SkillSwap — Project Story
🌟 Inspiration
The idea came from a simple frustration — great skills exist everywhere, but quality learning is locked behind paywalls. A friend wanted to learn web development but couldn't afford courses. He already knew graphic design — something others were paying hundreds for. That sparked the question:
Why can't people just trade what they know?
SkillSwap was born from that — a platform where knowledge is the only currency, and everyone has something worth sharing.
🛠️ How We Built It
| Layer | Technology |
|---|---|
| Frontend | React, Vite, Redux Toolkit, Tailwind CSS |
| Backend | Node.js, Express.js, Socket.io, Passport.js |
| Database | PostgreSQL + Supabase + Drizzle ORM |
| Auth | Google OAuth 2.0 + JWT + OTP Email Verification |
| Real-time | Socket.io (chat) + WebRTC (video) |
| Deployment | Vercel (frontend) + Render (backend) |
📚 What We Learned
- Real-time systems with Socket.io across separate deployment domains require careful CORS and transport configuration
- OAuth 2.0 flows are extremely sensitive — a single character mismatch in redirect URIs breaks the entire auth flow
- Designing a fair skill exchange system requires as much UX thinking as technical implementation
- Drizzle ORM + Supabase connection pooling behaves differently from standard PostgreSQL drivers
⚡ Challenges We Faced
1. Cross-Domain Authentication
Deploying frontend on Vercel and backend on Render meant Google OAuth redirect URIs had to be perfectly matched — a single typo broke everything.
2. Real-time Across Domains
Socket.io connections fail silently when CORS isn't configured correctly for separate domains. Debugging this took significant time.
3. Ephemeral File Storage
Render's free tier has no persistent disk — file uploads vanished on every redeploy. Solved by integrating Supabase Storage.
4. Session Planning Logic
Both users get a fair, auto-calculated exchange plan using:
$$\text{Sessions} = \left\lceil \frac{\text{Total Hours}}{\text{Hours per Session}} \right\rceil$$
So if User A needs 6 hours of Python and each session is 1.5 hours:
\( \lceil 6 / 1.5 \rceil = 4 \text{ sessions} \)
5. Database Connection Pooling
Supabase required prepare: false in the Drizzle config to prevent
prepared statement conflicts under connection pooling.
🚀 What's Next
- 📱 Mobile App — React Native for iOS & Android
- 🤖 AI Skill Matching — Smart recommendations based on goals
- 💬 Community Forums — Per-skill category discussions
- 🏆 Reputation System — Endorsements & verified skill badges
🔗 Links
- 🌐 Live App: skill-exchange-wrl8.vercel.app
- ⚙️ Backend: skill-exchange-0m3f.onrender.com
"Everyone knows something worth sharing — SkillSwap just makes it possible."
Built With
- axios
- css
- drizzle-orm
- express.js
- github
- google-oauth-2.0
- html
- javascript
- jwt
- multer
- node.js
- nodemailer
- passport.js
- postgresql
- react
- react-router-dom
- redux-toolkit
- render
- socket.io
- supabase
- tailwind-css
- vercel
- vite
- webrtc
Log in or sign up for Devpost to join the conversation.