Sakalim

Sakalim

About Me

September 28, 2024

Why You Should TRUST Frameworks (And What It Takes to Build One From Scratch)

10 min read

    listsfrontendarchitecturelearning

I’ve always had a love-hate relationship with frameworks. In today’s development world, you simply can’t meet production demands without weaving together multiple frameworks and libraries. They take care of the heavy lifting and the “dirty work” for you, which is great—until it’s not. The magic of a framework fades the moment you need something outside its box. That’s when you find yourself diving deep, hacking your way around it until things fit your use case.

But let’s face it: frameworks are here to stay. You might be an “old school” dev who believes you should write everything from scratch, and if that’s the case, this article might not be for you and I wish you good luck. For the rest of us, frameworks are essential, despite the occasional rough edges.

There’s a risk, of course. Using frameworks and libraries exposes your project to potential vulnerabilities—either through poor implementation or unmaintained code, or good forbidden malicious code. This is a topic for another day, but it’s worth keeping in mind as you pick your tools.

Introducing Unisphere (and What’s in It for You)

Unisphere is a meta-framework designed to tackle the core challenges modern developers face when building scalable and flexible frontend experiences.

While working on the framework, we gathered a list of questions that served as a checklist to ensure we were on the right track. Answering one or two is manageable, but answering them all requires careful planning. Our goal was for the framework to provide a rock-solid solution for today’s challenges as well as future ones. I’m sharing this list for you to review: The Key Questions Every Modern Frontend Framework Should Answer.

Why Should You Care About Unisphere?

Unisphere is more than just an internal framework for Kaltura—it’s a case study in how to address complex development problems. This series is filled with practical insights, architecture patterns, and code samples that you can adapt for your own projects.

Why it Works

Writing a framework is tough—writing it for internal use is even tougher. When a framework is your product (whether commercial or open source), you control its growth. You document, iterate, and refine based on your own needs. But when it’s built for internal use, you have to get it right from day one. If you don’t, your fellow developers won’t adopt it, and it’ll die before it even gets started.

Fortunately, my manager at Kaltura, Nir Belinki, saw the potential of an opinionated frontend framework. Unisphere was built to streamline developer workflows by separating infrastructure from the application layer. This allows developers to focus on features without worrying about underlying complexities.

By following a similar approach, you can increase productivity and simplify maintenance, making it a great model to learn from.

Why Is it a Meta-Framework?

Unisphere isn’t designed to replace core tools like React or NX. Instead, it builds on top of these technologies to solve higher-level architectural problems, such as runtime modularity, multi-environment integration, and scaling frontend systems efficiently.

While React is ideal for building UI components and NX is excellent for monorepo management, Unisphere extends these tools, adding the layers needed to address the complexities of integrating features across different applications and environments.

A Glimpse Into the Technology Stack

To deliver its solutions, Unisphere uses a variety of well-established technologies:

For efficient workflows, Commander.js offers a custom CLI, while Docusaurus powers documentation, ensuring that everything is easy to find and well-maintained.

In addition, all applications and runtime artifacts are hosted in a centralized AWS S3 bucket, which handles various types of artifacts—runtime scripts, single-page applications, and multi-page applications. This setup simplifies hosting, version control, and caching strategies, reducing the burden on dev-ops.

Finally, NX allows us to extend its capabilities with custom plugins and generators to automate workflows, create boilerplates, and manage continuous migrations. This helps developers evolve the codebase over time with minimal effort as new features are introduced or technologies change.

Wrapping It Up: The Multiplier Effect

As you can see, Unisphere leverages a wide array of techniques, libraries, and frameworks—and it does so with style. By clearly separating the infrastructure from the application layer and defining boundaries between them, it creates a powerful multiplier effect. A small team can maintain the infrastructure, empowering the rest of the developers to focus on delivering value, resulting in exponential gains in productivity.


What It Takes to Build a Framework From Scratch

Building a framework from scratch isn’t easy—it takes careful planning, clear objectives, and a deep understanding of your users. Based on my own experience with Unisphere, here are the core principles you need to keep in mind:

  1. Start with Clear Objectives: Define exactly what your framework is going to solve and what it isn’t. It’s crucial to know where your framework fits and who should use it. If you’re not sure what your goals are, your users won’t be either.

  2. Know Your Audience: Developers are your main users, so understand what they love and what frustrates them. For example, developers hate guessing. They need clear documentation, helpful code samples, and a supportive community. Make sure your framework delivers on these expectations from day one.

  3. Define Strong Concepts: Every framework needs a set of core concepts that guide its development. These concepts will be the foundation upon which everything else is built. Without a strong philosophical backbone, your framework can easily lose focus.

  4. Don’t Be Afraid to Change—But Know You Have Limited Time: Frameworks need room to evolve, but keep in mind that you only have a short window before your first official release to make significant changes. Early on, don’t hesitate to roll out ideas, test new approaches, or pivot from your original objectives. Use this time wisely by creating alpha and beta iterations, so you can remain flexible and gather valuable feedback before locking in decisions. Once the official version is out, making drastic changes becomes much harder without risking breaking functionality or backward compatibility.

  5. Prioritize Developer Experience (DX): Think about how the framework feels to use—smooth, intuitive, or frustrating and rigid? The developer experience should be a top priority. From setup to execution, every part of using your framework should be frictionless.

  6. Automate Everything You Can: Developers hate writing repetitive code, so automate whatever is possible. Build tools and command-line utilities that hide the complexity and let developers focus on what really matters: delivering the application itself.

  7. Remove Obstacles, Focus on Execution: Your framework should make developers’ lives easier, not harder. By removing barriers and solving common problems upfront, you free developers to focus on execution and delivering the actual requirements.

  8. Guard the Framework’s Role and Responsibilities: It’s important to maintain the framework’s core objectives and purpose. Users may request changes or patches that seem valid from their perspective but could work against the framework’s goals. Be cautious about introducing features that deviate from the framework’s responsibilities, as everything that becomes part of the public API or behavior must be supported long-term. Over time, this can make it difficult to deprecate or evolve certain aspects. Stay firm on what belongs within the framework and what doesn’t.

  9. Think Long-Term: It’s easy to design for the present, but if you don’t consider long-term use cases, you’ll struggle with backward compatibility down the road. Always keep future growth in mind to avoid unnecessary breaking changes later on.

  10. Log Everything: If your library is meant to be used by developers, logging is essential—log everything. You need detailed logs for every action your framework takes, and you should support a verbose mode for diagnostic debug logs. If your framework runs at runtime, expose it in a way that helps developers diagnose issues easily. No developer trusts a black box, and the more verbose your library is, the more trust you’ll build.

  11. Communicate Everything: Good documentation is non-negotiable. From day one, ensure you have a well-maintained, easy-to-navigate documentation site. Share your roadmap, be transparent about your plans, and invest time in making the experience appealing for users.

  12. Consider Migrations From Day One: When developers start using your framework, they will depend on you to provide smooth migrations as time passes. Every framework evolves, and if you don’t plan for migrations early, you risk causing frustration or even losing users down the road. Build in a strategy for versioning and migration tools from the beginning to ensure seamless transitions between versions without breaking existing implementations.

Ending Insight

I want to end this section with one final insight, which I believe is the most important of all:

Don’t Try to Remove the Learning Curve: Every framework comes with a learning curve—some steeper than others. Don’t try to satisfy everyone by oversimplifying your framework to the point where it doesn’t require learning. Be comfortable with the fact that developers will need to invest time in understanding how your framework works. Focus on attracting developers who are willing to learn and dive deeper, rather than those looking for shortcuts. If some developers choose not to invest the time, that’s their decision—but it doesn’t mean you need to compromise your framework’s depth or its long-term potential.


The Concepts Behind a Good Framework

Alright, enough storytelling—let’s get into the good stuff. After all, developers thrive on architecture, code and solid concepts, not just stories (we’ll leave that for the marketers).

If you’ve made it this far, I hope I’ve sparked your interest in what Unisphere brings to the table. Now, let’s dive into the core ideas that shape the framework.

Below, I’ve listed most of the key concepts that define Unisphere. Each of these will get its own dedicated article, where I’ll unpack them in detail.

It might take some time to cover everything, but don’t worry—I’ll be coming back to this article to update the links as I publish each new piece.

  1. Developer-Friendly: Maximize adoption by making the framework valuable and easy for developers to adapt.
  2. Diagnostics & Developer Tools: Built-in tools to simplify debugging, troubleshooting, and performance monitoring.
  3. Automate Everything with Boilerplates & Command Lines: Simplify processes by hiding complexity behind easy-to-use commands.
  4. Migrations in Mind: Ensure smooth updates and adaptations to changes with minimal friction.
  5. Runtime Discovery: Bridges the gap between loosely or non-coupled elements when used at runtime.
  6. Triple Usage Approach (NPM, Runtime, Standalone): Write once, without worrying about how it will be consumed later.
  7. Typed in a Non-Typed World: Maintain type safety with TypeScript, even in loosely coupled architecture.
  8. Built with SPA in Mind: Tailored for single-page applications, addressing their unique challenges and use cases.
  9. Clear Naming for Runtime: Establish clarity and consistency in naming conventions to avoid conflicts in runtime environments.
  10. Dogfooding Your Own Framework: Use the framework also internally to guarantee reliability, scalability, and continuous improvement.
  11. Versioning and Compatibility: Implement resilient versioning strategies that maintain backward compatibility while enabling the introduction of breaking upgrades.
  12. Collaboration with Partners: Facilitate smooth integration with external elements that aren't part of the framework.
  13. Flexible Dependency Strategy: Resolve dependency conflicts in NPM packages without losing flexibility by introducing a new balanced strategy (details in the future article).
  14. Framework Agnostic: Design the public API in vanilla JavaScript, allowing it to integrate with any framework, despite using React internally.​

What’s Next?

This article sets the stage for understanding the challenges and concepts involved in building a framework like Unisphere. But there’s much more to come! In the coming weeks, I’ll be releasing a multi-part series titled “A Practical Guide to Scaling Frontend Experiences,” where we’ll explore real-world scenarios for scaling features across multiple applications. You can start with Part 1 here.

I’ll also delve deeper into the concepts mentioned here and link each back to this article.

Additionally, I’ll be sharing boilerplates, code samples, and other guides that Unisphere has to offer.

If you’d like to be notified when new articles are released, follow me on dev.to and stay in the loop!