How I Built This Platform
The story behind this site — from scattered tools and failed experiments to a zero-cost learning platform that actually works.
How I Built This Platform
This post isn't about the tech stack or the architecture — you can find those in the tech stack post and the course overview. This is the story of why I built it, the problems I ran into, and the decisions that shaped what you see today.
The Problem
For years, my content lived in a dozen different places.
Scattered across Google Docs, Notion, and random markdown files
Some on Medium, some in drafts that never got published
GitBook for one project, README files for another
PowerPoint slides, PDFs, handwritten notes — everywhere
Every time I wanted to share something, I'd have to remember where I put it, update it in one place, forget to update it in another. It was a mess.
I wanted one place — a single repo, a single URL — where everything lives together.
Attempt #1: Stripe Payments (Failed)
When I decided to offer a paid course, my first instinct was Stripe. It's the gold standard, right?
Stripe requires a registered business entity to accept payments in India. As a freelancer without a registered business, I couldn't get past the onboarding.
On top of that, the Stripe SDK crashed my Next.js build because it tried to initialize at module evaluation time — before environment variables were available.
I spent a weekend wiring up Stripe checkout, webhooks, and success pages. Then I realized none of it would work for my situation. Deleted it all.
Attempt #2: Manual UPI (Worked!)
I stepped back and thought about what I actually needed:
- Student pays me ₹125
- I verify the payment
- They get access
That's it. I don't need a payment gateway for that. I need a UPI QR code and a way to verify transactions.
The payment page shows a dynamically generated QR code with the amount pre-filled. Student scans, pays, enters their transaction ID, and I get an email. One tap to approve. Done.
No Stripe. No Razorpay. No business registration. Zero payment gateway fees.
The Email Problem
I started with Resend for sending admin notification emails. The emails were technically delivered — I could see them in Gmail search — but they wouldn't render properly. You'd click on the email and see a blank screen.
I tried debugging Resend's delivery for a while before realizing: I'm overcomplicating this. Gmail can send emails to Gmail. Why am I using a third-party service?
Switched to Nodemailer with Gmail SMTP using a Google App Password. Took 10 minutes. Emails land in my inbox instantly, render perfectly, and cost ₹0.
One-Click Approval
The admin dashboard I built works fine, but I'm lazy. I don't want to open a browser, navigate to /admin/payments, and click approve every time someone enrolls.
So I built HMAC-signed approval links directly in the notification emails. When someone requests access or pays for a course, I get an email with a big green button. One tap from my phone → student is enrolled.
The approve link contains the user ID, course ID, and a cryptographic signature generated with my Clerk secret key. It can't be forged or replayed — if anyone tampers with the URL parameters, the signature check fails.
No Database, No Problem
One of the best decisions I made was not using a database.
MDX files in the repo — version-controlled, easy to edit
Clerk's publicMetadata — roles, enrollments, pending requests
localStorage in the browser — per-lesson completion tracking
Email trail + Clerk metadata — enough for my scale
For a single-creator platform, this is more than enough. If I ever need a database, I'll add one. But right now, zero infrastructure means zero maintenance.
Meeting Scheduling
Once the site was live, people started reaching out to connect. I needed a way to let visitors book time without the back-and-forth of "are you free Tuesday?"
I integrated Cal.com for meeting scheduling. It's open-source, connects to Google Calendar, and auto-generates Google Meet links. The embed loads inline on the /meet page — no redirects, no iframes fighting with styling.
The integration is dead simple — the official @calcom/embed-react package provides a <Cal> React component that renders the scheduling widget right on the page. Visitors pick a 15-minute slot, Cal.com handles calendar conflicts, and a Google Meet link is generated automatically.
The ₹0/Month Stack
This was a deliberate goal from the start. Every tool I chose is either free or has a generous free tier.
Vercel — free tier
Clerk — free tier
Gmail SMTP — free
UPI — no gateway fees
Cal.com — free tier
GitHub repo — free
Curated Programs
The generic courses work for most learners, but sometimes people need a tailored curriculum. A DevOps course that covers everything from Kubernetes to Ansible might be overkill for someone who only needs K8s + CI/CD.
So I built a curated programs system — think Spotify playlists for lessons. I pick specific lessons from any course, bundle them into a named program, and enroll the student in just those lessons.
Programs don't copy lessons — they just reference existing MDX files by path. A program like "Vedika's DevOps + AI" might pull 2 lessons from DevOps and 7 from AI Bootcamp. Same content, different playlist.
The student sees only their curated lessons with progress tracking scoped to the program. The enrollment flow uses the same HMAC approve links — I just enroll them in a program ID instead of a course ID.
On the learning catalog, programs appear as a single "Curated Programs" umbrella card alongside the courses — clicking it opens a dedicated listing page at /programs, which then links to each individual program. Same folder-style navigation as courses.
To make creating programs easier, I built an admin program builder at /admin/programs. It's a visual wizard — pick an icon, fill in details, browse all available lessons in a tree, check the ones you want, reorder them, and download a JSON file. Drop the file in content/programs/ and push. No TypeScript editing required.
Lessons Learned
- Start simple — I wasted time on Stripe when a QR code was all I needed
- Use what you already have — Gmail sends emails, Clerk stores data,
localStoragetracks progress - Don't build for scale you don't have — a database is overhead when Clerk metadata does the job
- Signed URLs are underrated — HMAC links let me handle admin actions from email without logging in
- MDX is powerful but quirky — complex JS in props breaks the parser, use children-based patterns instead
- Embed, don't rebuild — Cal.com handles scheduling better than anything I'd build myself
What's Next
- More courses and lessons
- Certificate generation on course completion
- Community discussion threads
- Mobile-optimized reading experience
If you want the technical details, check out the tech stack and course overview posts. And if you're building something similar — reach out, happy to help.