๐Ÿ‘จโ€๐Ÿซ Week 1 of Building Edly: Schemas, Structure, and Smart Choices

Anmol KhatriAnmol Khatri
5 min read

Every big product starts with a small step โ€” this week, I took mine.

Welcome to Week 1 of building Edly, a full-stack online course platform focused on giving educators their own branded subdomains (like anmol.edly.com) and complete autonomy over their content.

๐Ÿš€ Introduction

As a passionate developer focused on solving real problems, I started building a full-stack scalable learning platform where educators can create their own branded subdomains, manage courses, and monetize their knowledge. The goal was simple:

Let any educator/creator launch their own mini version of Udemy โ€” fully controlled, fully branded, and scalable โ€” without the need to build a platform from scratch.

This series of blogs will be a full documentation of my technical journey: every decision I made, why I made it, what alternatives I considered, where I struggled, and what I learned.

๐Ÿ”ง The Problem I Wanted to Solve

Many educators want to build branded learning platforms with:

  • Subdomains (e.g., anmol.edly.com)

  • Control over content

  • Built-in monetization

  • Certificate issuing

  • Analytics

But existing solutions like Udemy, etc., don't offer true autonomy. So I envisioned a centralized platform (like Shopify for learning) that gives individual educators their own admin control and learning environment under subdomains.


๐Ÿง  Phase 1: Architecting the System

I decided to start with the MERN stack:

  • MongoDB: Flexible schema โ€” perfect for course/content hierarchy.

  • Express.js + Node.js: Lightweight and scalable backend.

  • React.js (Coming soon): Dynamic UI for student and educator interfaces.

  • Subdomains architecture: Each educator has a unique space like anmol.edly.com.

๐Ÿงฉ Why MongoDB?

  • Schema flexibility: Each course has modules โ†’ modules have lessons/pdfs/quizzes.

  • Easy to embed related structures or reference them for performance.

  • Designed for read-heavy platforms with document-based content.

๐Ÿ—‚ Deciding Between Monolith vs. Microservices

Although microservices seem attractive for scalability, I stuck with a monolithic architecture for Phase 1 due to:

  • Faster iteration

  • Easier debugging

  • No infrastructure overhead

In the future, once I hit scale, I can break services like auth, content, and analytics into microservices.


๐Ÿ” Phase 2: Setting Up Educator Onboarding & Authentication

I started with the educator flow first:

  • /register: Register an educator with a subdomain and basic profile.

  • /login: Log in to access the dashboard.

  • /onboarding: A simple form to collect organization details, bio, etc.

๐Ÿงฑ Educator Schema

const educatorSchema = new mongoose.Schema({
  firstName: String,
  lastName: String,
  emailId: { type: String, unique: true },
  password: String,
  subdomain: { type: String, unique: true },
  bio: String,
  organization: String,
});

I chose to assign a unique subdomain per educator. Later, this will help me configure dynamic routing or proxy setups for subdomains like anmol.edly.com.

๐Ÿ” Auth Controller

  • JWT-based auth

  • Middleware to attach req.user

  • Only logged-in users can create courses, modules, content


๐Ÿ“ฆ Phase 3: Designing Course โ†’ Module โ†’ Content Hierarchy

This was a major design decision. I explored multiple options and faced a few challenges:

Option 1: Nest Everything (Embed modules & lessons inside course)

โœ… Simple, easy access
โŒ Hard to update independently
โŒ Inflexible for future analytics

Option 2: Normalize Everything (Separate models + references)

โœ… Scalable
โœ… Easily update lessons, modules
โœ… Trackable analytics
โœ… Works well with subdomain filtering

๐Ÿง  I chose Option 2. Hereโ€™s the architecture:

  • Course: created by educator

  • Module: belongs to a course

  • Content: contains either a video lesson, PDF, or quiz

  • Content items are referenced with a flexible field


๐Ÿ— Models I Created

๐Ÿ“˜ Course

title, description, thumbnail, price,
aboutCourse (6 paragraphs),
highlights (5 one-liners),
educatorId (ref)

๐Ÿ“ Module

title,
courseId (ref),
content: [ { type: 'lesson' | 'pdf' | 'quiz', refId } ],

๐Ÿ“„ Content Models (Separate for clarity)

  • Lesson:

    • title, videoUrl, moduleId
  • PDF:

    • title, pdfUrl, moduleId
  • Quiz:

    • title, questions[], moduleId

๐Ÿ”„ Controllers Created

  • courseController.js

  • moduleController.js

  • lessonController.js

  • pdfController.js

  • quizController.js

Each one has:

  • create

  • delete

  • For modules, an updateModuleContent to add new lessons/pdfs/quizzes in sequence

โœ… Lesson of the Day: Maintain Sequence

I struggled a bit with how to store content in a proper order.

Solution: A content[] array inside Module with type + refId pattern. This lets me maintain the order as they were added by the educator.


๐Ÿ” Problem I Encountered

โ“ โ€œHow will students know which courses they can access?โ€

โœ… Solution: On course creation, I store educatorId โ†’ then during API calls, filter based on the logged-in educator.

โ“ โ€œHow do I maintain modularity for updates?โ€

โœ… Solution: Normalize everything. Independent models make it easy to update/delete without touching the parent document.

โ“ โ€œShould I use MongoDBโ€™s default _id or custom IDs?โ€

โœ… Used MongoDBโ€™s _id โ€” theyโ€™re unique, indexed, and scalable.


๐Ÿ“Š Future Scope ( Coming Soon)

  • Student flows: registration, enroll in course, access content

  • Doubt engine: raise questions, educators reply

  • Live class integration (e.g., Jitsi/Zoom APIs)

  • Subdomain handling with reverse proxy (e.g., Nginx/Express middleware)

  • Payment system: Stripe integration

  • Certificate issuing engine

  • Dashboards for educators: analytics, earnings, student behavior


๐Ÿ“š What I Learned

  • Donโ€™t over-engineer early โ€” monolith was the right choice.

  • MongoDB gives you enough flexibility but use references smartly.

  • Auth flow is key to controlling access and visibility.

  • Always think about "who can see/edit what?" while building APIs.

  • Document your journey โ€” helps you reflect, debug, and share.


โœจ Final Thoughts

This journey is not just about building a project โ€” itโ€™s about design thinking, problem-solving, and developing a mindset for scale. By carefully choosing the right architecture and anticipating future needs, Iโ€™ve laid the foundation for a powerful learning platform.

Iโ€™ll be uploading a new blog every Wednesday as I continue building this platform, until the project is complete. Each post will dive deeper into key features, tech decisions, and lessons learned along the way.

If you're an aspiring full-stack developer โ€” remember:

Start simple. Validate. Iterate. Scale.


๐Ÿ”— Connect with Me

If you found this helpful or have feedback, connect with me on GitHub or Linkedin.

Stay tuned for the next blog โ€” where Iโ€™ll build out the student-side APIs and begin rendering content dynamically via React. ๐Ÿš€

0
Subscribe to my newsletter

Read articles from Anmol Khatri directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anmol Khatri
Anmol Khatri