How to Build a Course Platform as a Solo Developer
Step-by-step guide to building an online course platform by yourself. Tech stack, timeline, costs, and practical advice.
What You're Building
An online course platform where creators can publish video courses, written content, quizzes, and structured learning paths. Students enroll, progress through modules, and earn completions. Think of it as your own Udemy or Teachable, but focused on a specific niche or built to sell your own courses.
Let me be upfront about something. If you just want to sell a course, don't build a platform. Use Teachable, Podia, or Gumroad. They handle payments, hosting, and delivery. Building your own platform only makes sense if you want to create a marketplace for multiple creators, need custom features those platforms don't offer, or plan to make the platform itself your product.
I say this because I've seen at least a dozen solo developers build custom course platforms when they should have just used Teachable. They spent months on video hosting and payment processing instead of actually creating course content. Don't fall into that trap.
Difficulty & Timeline
| Aspect | Detail |
|---|---|
| Difficulty | Hard |
| Time to MVP | 3-5 months |
| Ongoing Maintenance | High |
| Monetization | Course sales, subscriptions, platform fees |
Recommended Tech Stack
Next.js (latest is 16.2.6 on npm as of May 30, 2026) for the frontend and API. Video hosting through Mux (their pricing is reasonable and they handle adaptive streaming, which is something you absolutely do not want to build yourself). PostgreSQL (current major line is 18, with 18.4 released May 14, 2026) for the database. Stripe for payments (the official stripe Node SDK is at 22.2.0, with @stripe/stripe-js at 9.7.0).
For the video player, use Mux's player component (@mux/mux-player-react is at 3.13.0) or Video.js (video.js is at 8.23.7). Rolling your own video player is a rabbit hole that never ends. Trust me on this. Adaptive bitrate streaming, resume playback, playback speed controls. Mux handles all of it, and its pricing has actually gotten cheaper over time. As of May 30, 2026 the Mux Free plan includes 100,000 delivery minutes per month and up to 10 stored videos, and pay-as-you-go delivery starts at $0.0008 per minute for 720p (scaling up with resolution to roughly $0.0032 per minute at 4K). Encoding on the Basic tier is free, and storage starts at $0.0024 per minute. Check current pricing before you model your unit economics, because these rates move.
If you're building this as a marketplace for other creators, you'll also need Stripe Connect for splitting payments between the platform and creators. This adds complexity but Stripe's documentation walks you through it well enough. Budget for the Connect fees on top of the standard 2.9% + $0.30 per card transaction. On the "you handle pricing" model for Express and Custom accounts, Stripe charges $2 per monthly active connected account, plus 0.25% + $0.25 per payout sent, plus 0.25% of payout volume for funds routing (verified on Stripe's Connect pricing page on May 30, 2026).
Step-by-Step Plan
Phase 1: Foundation (Month 1)
Start with the data model. Courses contain modules. Modules contain lessons. Lessons have content (video, text, or both). Students have enrollments. Enrollments track progress per lesson. Get this right and everything else flows from it.
Set up authentication with role-based access. You need at least three roles: admin, instructor, and student. Use Clerk (@clerk/nextjs is at 7.4.2 on npm as of May 30, 2026) or NextAuth/Auth.js for this. One gotcha worth flagging up front: the package published as next-auth is still on the v4 line (4.24.14), while the actively developed successor ships under the Auth.js branding, so check which major you actually want before you wire it in. Implementing role-based permissions from scratch is tedious but necessary if you're building a platform.
Build the instructor dashboard where creators can create courses, add modules, upload videos, and write lesson content. This is the unsexy but critical part. If creating a course is painful, no one will use your platform. I've used course platforms where uploading a single video took five clicks and a page refresh. Those platforms didn't last.
Phase 2: Core Features (Month 2-3)
Build the student experience. Course catalog, enrollment, lesson viewer, and progress tracking. The lesson viewer is the heart of your platform. It needs to play video smoothly, display written content alongside it, and save progress automatically.
Implement progress tracking at the lesson level. When a student finishes a lesson, mark it complete and update the overall course progress. This sounds simple, but the edge cases add up. What if they watch 90% of a video? What if they skip around? I'd recommend marking a lesson complete either when the video reaches 90% or when the student clicks a "mark complete" button. Don't try to get clever with tracking exact watch time unless you have a specific reason.
Add a simple quiz or assessment system if it fits your niche. Multiple choice questions stored as JSON in your database work fine for v1. Don't build a full assessment engine. A few questions after each module to reinforce learning is enough.
Phase 3: Polish & Launch (Month 4-5)
Handle the video pipeline properly. Instructors upload raw video files. You process them through Mux (or your chosen provider), which generates multiple quality levels and a streaming URL. Store the Mux asset ID in your database and use their player to stream.
Add email notifications. Welcome emails on enrollment, reminders for incomplete courses, and completion certificates. These seem like nice-to-haves, but they dramatically improve course completion rates. Resend or SendGrid handles the transactional email side. Resend's resend SDK is at 6.12.4 (npm, May 30, 2026), and its free plan covers 3,000 emails per month capped at 100 per day, with the Pro plan at $20 per month for 50,000 emails. SendGrid's free email plan has tightened, so verify its current limits before committing; its paid Essentials tier starts at $19.95 per month. For a solo build the free Resend tier is usually plenty to launch on.
Build a proper landing page for each course. Title, description, instructor bio, curriculum overview, student reviews, and a clear "enroll now" button. This is your sales page. Every conversion optimization matters here.
Monetization Strategy
There are three main models for course platforms.
Sell your own courses. If you're the instructor, you keep 100% minus payment processing fees. Price courses at $49-199 for one-time access or $19-49/month for a subscription that includes all courses. One-time purchases are simpler to implement but subscriptions generate recurring revenue.
Marketplace with revenue share. Charge instructors a platform fee (10-30% of each sale). This is how Udemy and Teachable work. You need a critical mass of instructors and students for this model to work, so it's harder to bootstrap.
Subscription platform. Charge students a monthly fee ($15-39/month) for access to all courses. Pay instructors based on engagement (watch time or completions). This is the Netflix model, and it works well when you have a library of content.
For a solo developer, I'd start with selling your own courses. Build the platform, create one excellent course, and sell it. Use the revenue to fund platform development. Only open it to other instructors once you've validated that the platform itself works.
Completion certificates are a surprisingly effective monetization lever. People share certificates on LinkedIn, which drives organic traffic. Make certificates look professional and include a verification URL back to your platform.
Common Mistakes to Avoid
Building the platform before creating any content. The platform is worthless without courses. Write or record at least one complete course before you build anything. Use Google Docs and Loom recordings. If people buy the rough version, then build the platform.
Hosting your own video. Video hosting, transcoding, and adaptive streaming are incredibly hard problems. Use a managed provider. Self-hosting video is a full-time infrastructure job. Your S3 bill alone will surprise you, and you'll still have buffering issues. As of May 30, 2026 the three I'd compare are Mux (Free plan with 100,000 monthly delivery minutes, then delivery from $0.0008 per minute), Cloudflare Stream ($5 per 1,000 minutes stored per month plus $1 per 1,000 minutes delivered), and Bunny Stream (storage from $0.01 per GB per month, delivery from $0.005 per GB, with encoding included at no extra cost). The pricing models differ enough (per-minute versus per-GB) that you should run your own numbers, but any of the three beats running your own transcoding farm.
| Provider | Storage | Delivery | Encoding |
|---|---|---|---|
| Mux | from $0.0024/min | from $0.0008/min (720p), 100K free min/mo | Basic tier free |
| Cloudflare Stream | $5 / 1,000 min stored | $1 / 1,000 min delivered | included |
| Bunny Stream | from $0.01/GB/mo | from $0.005/GB | included (no transcoding fee) |
All figures verified on each vendor's pricing page on May 30, 2026. Confirm current rates before you model unit economics.
Overcomplicating the course structure. Courses, modules, lessons. That's all you need. Don't add learning paths, prerequisites, branching logic, or adaptive learning in v1. Every feature you add multiplies the complexity of your instructor interface.
Skipping mobile optimization. A huge percentage of online learning happens on phones and tablets. If your video player doesn't work well on mobile and your lesson text isn't readable on a small screen, you're losing students. Test on real devices, not just browser dev tools.
Is This Worth Building?
It depends on why you're building it. If you have expertise to teach and want a custom platform, yes. The online education market is enormous and still growing. People pay $50-200 for a good course without blinking. If you build the platform and the content, the margins are excellent.
If you're building a marketplace to compete with Udemy or Coursera, that's a much harder sell. You need both supply (instructors) and demand (students), and the chicken-and-egg problem is brutal. You'd need to recruit instructors first, probably by offering them better terms than the big platforms.
My honest advice: start by selling a course on an existing platform. If it does well, then consider building your own. The course content is the hard part. The platform is just plumbing. I've seen developers spend six months building a beautiful course platform and then realize they had nothing to teach on it. Don't be that developer.
Common Errors and Fixes
These are the integration snags that eat the most time when you wire up the stack above. Each one maps to a documented behavior, not a guess.
Stripe webhook signature verification fails ("No signatures found matching the expected signature"). The most common cause in a Next.js App Router project is that the framework has already parsed the request body, so the bytes Stripe signed no longer match what you pass to stripe.webhooks.constructEvent. Read the raw body before any JSON parsing (in the App Router, use await req.text() and pass that string), and make sure the STRIPE_WEBHOOK_SECRET you verify against is the one for the exact endpoint that received the event. Stripe's webhook docs cover the raw-body requirement explicitly.
Mux playback returns a 403 or the player shows "Not Found." If your asset uses signed playback, an unsigned playback_id will be rejected. Either create the asset with a public playback policy for non-gated content, or generate a signed JWT for the playback ID and pass it as the player's playback-token. Also confirm the asset's status is ready before you try to play it, because an asset still in preparing has no streamable rendition yet.
Clerk middleware throws "auth() was called but Clerk can't detect usage of clerkMiddleware()." This appears after upgrading @clerk/nextjs if your middleware.ts still uses the old authMiddleware export. The current major expects clerkMiddleware() from @clerk/nextjs/server and a matcher that includes your API and app routes. Update the middleware export and the matcher config to match the version you installed.
Resend or SendGrid send fails silently or returns a 403 on a custom from-address. Transactional providers will not deliver from a domain you have not verified. Add and verify your sending domain (SPF and DKIM records) before sending, and during development send from the provider's allowed sandbox or onboarding address. Also remember the daily caps: Resend's free plan allows 100 emails per day even though the monthly allowance is 3,000, so a burst of enrollment emails can hit the daily ceiling.
PostgreSQL migration fails after a Next.js or ORM upgrade. Pin your database major version in local, staging, and production to avoid feature drift, and run migrations against the same major you ship on. PostgreSQL 14 stops receiving fixes on November 12, 2026, so if you are still on 14 plan the jump to a supported major (16, 17, or 18) before that date rather than after a forced outage.
Sources
- Next.js latest version (
16.2.6), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/next/latest - Stripe Node SDK latest version (
22.2.0), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/stripe/latest @stripe/stripe-jslatest version (9.7.0), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/@stripe/stripe-js/latest@clerk/nextjslatest version (7.4.2), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/@clerk/nextjs/latestnext-authlatest version (4.24.14), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/next-auth/latest@mux/mux-player-reactlatest version (3.13.0), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/@mux/mux-player-react/latestvideo.jslatest version (8.23.7), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/video.js/latestresendlatest version (6.12.4), npm registry, checked-on 2026-05-30: https://registry.npmjs.org/resend/latest- Mux Video pricing (Free plan 100K delivery min/mo, delivery from $0.0008/min, storage from $0.0024/min, Basic encoding free), checked-on 2026-05-30: https://www.mux.com/pricing/video
- Stripe standard card fee (2.9% + $0.30), checked-on 2026-05-30: https://stripe.com/pricing
- Stripe Connect pricing ($2/monthly active account, 0.25% + $0.25 per payout, 0.25% funds routing), checked-on 2026-05-30: https://stripe.com/connect/pricing
- Cloudflare Stream pricing ($5/1,000 min stored, $1/1,000 min delivered), checked-on 2026-05-30: https://developers.cloudflare.com/stream/pricing/
- Bunny Stream pricing (storage from $0.01/GB/mo, delivery from $0.005/GB, encoding free), checked-on 2026-05-30: https://bunny.net/stream/
- Resend pricing (free plan 3,000 emails/mo capped at 100/day, Pro $20/mo for 50,000), checked-on 2026-05-30: https://resend.com/pricing
- SendGrid / Twilio Email API pricing (Essentials from $19.95/mo, free plan limits tightened), checked-on 2026-05-30: https://www.twilio.com/en-us/products/email-api/pricing
- PostgreSQL 18.4 release and version 14 end-of-life (November 12, 2026), checked-on 2026-05-30: https://www.postgresql.org/about/news/postgresql-184-1710-1614-1518-and-1423-released-3297/
Like this? You'll like what I'm building too.
Two ways to support and get more of this work.
HEARTH
A privacy-first Life OS for your desktop. Journal, tasks, and notes that stay on your machine. Coming soon, direct download from this site.
Read moreMY TOOLKITS
Receipts-first toolkits for shipping after hours, building Claude agents, publishing on Amazon, and more. The exact methods I used, not theory.
Browse on WhopRelated Articles
Treating Video As Code With Remotion And fal
How I turned a script into a finished video with code instead of a timeline app, and why determinism is the real win for a solo dev.
Build Versus Buy For A Custom AI Feature
How to decide between an off-the-shelf AI tool and a custom AI feature, weighing control, cost, differentiation, and data with a clear framework.
Can One Developer Build Your Whole MVP
An honest look at whether a single full-stack developer can ship your whole MVP, when it works beautifully, and when you should bring in more people.