Skip to content

Blog Home

Is Mesop + Web Components the cure to Front-end fatigue?

I saw this tweet the other day and couldn't help but chuckle:

At first, I thought of it as joke, but now that Mesop has launched experimental support for Web Components, I think it's plausible that Mesop with Web Components can save you from front-end fatigue.

What is Mesop?

Before we dive in, let me explain what Mesop is. Mesop is a Python UI framework focused on rapidly building AI apps. You can write a lot of kinds of apps all in Python as you can see from the examples on our home page, but when you need to, Mesop provides the flexibility of dropping down into web components so you can have fine-grained UI control and use existing JS libraries.

Avoid the builds

Programming meme

DHH, creator of Rails, recently gave an interview saying how he's "done with bundling" and the overall complexity of modern front-end build toolchains.

As someone who's done front-end for almost a decade, I can attest to the sentiment of feeling the pain of compiling JavaScript options. Setting up compiler configs and options can easily take hours. I want to be clear, I think a lot of these tools like TypeScript are fantastic, and the core Mesop framework itself is compiled using TypeScript and Angular's compilers.

But when it comes to rapid prototyping, I want to avoid that overhead. In our design proposal, we intentionally designed a lightweight model where you don't need to set up a complex build chain to start writing JavaScript.

Sometimes a build step is unavoidable, e.g. you're writing TypeScript, and you can still compile your JavaScript as needed.

Framework churn

The front-end ecosystem is infamous for its steady and constant churn. The good thing about building on top of web components is that it's based on web standards supported by all modern browsers. This means, that given browser makers' focus on "not breaking the web", this will be there for many years, if not decades to come.

For years, web components had a reputation of being an immature technology due to inconsistent support across browsers, but fast forward to 2024, and web components are well-supported in modern browsers and libraries built on web components like Lit, which is downloaded millions of times a week.

Minimizing front-end fatigue in Mesop

FE developers are so used to the pain and complexity of front-end development that they can forget how steep the learning curve is until someone from another domain tries to build a simple web app, and struggles with just getting the web app up and started.

Mesop app developers are mostly not front-end developers which means that reducing the complexity, especially learning curve, of building custom components is very important. In Mesop, we've designed a smooth pathway where you can get started with a little front-end knowledge and build simple custom components without learning a complex front-end framework.

What's next

Follow our X/Twitter account, @mesop_dev for more updates. We're working on improving our web component support, in particular by:

  • Creating guides for wrapping React components into Mesop web components
  • Fostering an ecosystem of open-source Mesop web components by making it easy to discover and reuse web components that other people have built.

We're excited about the potential of Mesop and Web Components to simplify front-end development. Whether it's the cure for front-end fatigue remains to be seen, but I think it offers a promising alternative to the complexity of traditional front-end development.

Why Mesop?

Mesop is a new UI framework that enables Python developers to quickly build delightful web apps in a scalable way.

Many Python UI frameworks are easy to get started with, but customizing beyond the defaults often requires diving into JavaScript, CSS, and HTML — a steep learning curve for many developers.

Mesop provides a different approach, offering a framework that's both easy to learn and enables flexible UI building, all within Python.

I want to share a couple concrete ways in which Mesop achieves this.

Build UIs with Functions (i.e. Components)

Mesop embraces a component-based philosophy where the entire UI is composed of reusable, building blocks which are called components. Using a component is as simple as calling a Python function. This approach offers several benefits:

  • Simplicity: You can use your existing Python knowledge to build UIs quickly and intuitively since components are just functions.
  • Maintainability: Complex UIs become easier to manage and understand by breaking them down into smaller, focused components.
  • Modularity: Components are self-contained, enabling easy reuse within a project or across different projects.

Here's an example of a reusable icon button component:

def icon_button(*, icon: str, label: str, tooltip: str, on_click: Callable):
  """Icon button with text and tooltip."""
  with me.content_button(on_click=on_click):
    with me.tooltip(message=tooltip):
      with me.box(style=me.Style(display="flex")):
        me.icon(icon=icon)
        me.text(
          label, style=me.Style(line_height="24px", margin=me.Margin(left=5))
        )

Flexibility through Layered Building Blocks

Mesop provides a range of UI building blocks, from low-level native components to high-level components.

  • Low-level components: like box, offer granular control over layout and styling. They empower you to create custom UI elements through flexible layouts like flexbox and grid.
  • High-level components: like chat, are built from low-level components and provide ready-to-use elements for common use cases, enabling rapid development.

This layered approach makes deep customization possible. This means that if you want to customize the chat component, you can fork the chat implementation because it's written entirely in Python using Mesop's public APIs.

See Mesop in Action

To demonstrate the range of UIs possible with Mesop, we built a demo gallery to showcase the types of applications you can build and the components that are available:

The demo gallery itself is a Mesop app and implemented in a few hundred lines of Python code. It demonstrates how Mesop can be used to create polished, custom UIs in a maintainable way.

Try Mesop

If this sounds intriguing, read the Getting Started guide and try building your own Mesop app. Share your feedback and contribute as we continue developing Mesop.

Visual Editor

Why?

As I began discussing Mesop with friends and colleagues, one thing that has come up is the difficulty of teaching and persuading non-frontend engineers to build UIs, even simple ones. CSS, particularly the rules around layout, can be quite challenging and off-putting.

I've developed a new visual editor for Mesop that aims to make UI building more approachable for beginners and more productive for experts.

What?

Let's take a look at the visual editor:

Visual Editor v1

With the visual editor, you can:

  • Add new components into your app
  • Modify existing components
  • Visualize the component tree hierarchy
  • You can inspect existing components on the page by hovering over them and then change them in the editor panel
  • Bring Your Own components. By decorating a Python function with me.component, you've turned it into a Mesop component and you can now add it with the visual editor.

What's exciting about the visual editor is that you aren't locked into it - everytime you change a component with the visual editor, it's modifying the source code directly so you can seamlessly go back forth between a regular text editor and the visual editor to build your Mesop app.

Prior Art

Visual editors (aka WYSIWYG builders) have been around for a long time. Puck is one of the most interesting ones because of a few reasons: 1) it's open-source, 2) it's flexible (e.g. bring your own components) and 3) it's intuitive and easy-to-use.

The main issues I saw with Puck, particularly for Mesop's use case, is that it currently only supports React (and Mesop uses Angular) and Puck saves data whereas I would like Mesop's Visual Editor to directly emit/update code, which I'll explain next.

Principles

Hybrid code (not low-code)

One of the reasons why WYSIWYG builders have not gotten much traction with engineers is that they're often good for simple applications, but then you hit a wall building more complex applications.

To avoid this issue, I'm focusing on making the Visual Editor actually emit code and not just data. Essentially, the UI code that you produce from the Visual Editor should be the same as the code that you would write by hand.

Unobtrustive UI

I want Mesop app developers to do most of their work (except for the final finetuning for deployment) in the Visual Editior which means that it's important the Editor UI is un-obtrusive. Chrome DevTools is a great example of a low-key tool that many web developers keep open throughout their development - it's helpful for debugging, but then it's out of your way as you're interacting with the application.

Concretely, this means:

  • Editor UI should be collapsible
  • You should be able to "disable" the editor mode and interact with the application as a normal user.

Contextual

The visual editor should provide only the information that you need when you need it.

For example, rather than showing all the style properties in the editor panel, which would be quite overwhelming, we only show the style properties that you're using for the selected component.

Local-only

Because the Visual Editor relies on editing files in your local filesystem, I want to avoid any accidental usages out in the wild. Concretely, this means that you can only use the Visual Editor in localhost, otherwise the Mesop server will reject the editor edit requests.

What's next

There's still a lot of improvements and polishes I would like to make to the visual editor, but a few high-level ideas that I have are:

  1. Build example applications using the visual editor with a video walkthrough.
  2. Create more high-level components in Mesop Labs, which I'll introduce in an upcoming blog post, to make it even easier to build apps with the visual editor.
  3. Drag and drop components onto the page and within the page. This will provide an intuitive experience for building the UI, literally block by block.

Hello, Mesop

After working on Mesop for the last two months, I'm excited to finally announce the first version of Mesop, v0.1. This is still early days for Mesop, but it's an important milestone because it represents a minimum viable tool for building UIs in Python. In case you haven't read Mesop's home page, Mesop is a Python-based UI framework that allows you to rapidly build web demos. Engineers without frontend experience can build web UIs by writing idiomatic Python code.

Why Mesop?

Mesop is in many ways a remix of many existing ideas packaged into a single cohesive UI framework, designed for Python developers. I've documented some of these goals previously, but I'll quickly recap the benefits of Mesop here:

  • Allows non-frontend engineers to rapidly build UIs for internal use cases like demos.
  • Provides a fast build-edit-refresh loop through hot reload.
  • Enables developers to benefit from the mature Angular web framework and Angular Material components.
  • Provides a flexible and composable components API that's idiomatic to Python.
  • Easy to deploy by using standard HTTP technologies like Server-Sent Events.

What's next for Mesop?

I see a few broad themes of work in the coming year or so.

Expand Mesop's component library

Mesop's current component library is a solid start but there's still gaps to support common use cases.

Areas of work:

  • Complete Angular Material component coverage. We support 13+ Angular Material components today, however there's many more that we don't support. Some of it is because I haven't had time to wrap their components, but in other cases (e.g. sidenav), I'd like to spend more time exploring the design space as it will probably require supporting some kind of multi-slot component API. Getting this API designed correctly, for not just this component but also future components, is important in the long run.

  • Support more native HTML elements/browser APIs. Right now, only Box and Text are thin wrappers around native HTML elements. However, there are other HTML elements like <img>, <audio> and <video> that I'd like to also support. The flip side of supporting these components is enabling a way to allow Mesop end-users to upload these media contents, which there are also native browser APIs for.

  • Custom components. Some components won't belong in the standard Mesop package because it's either too experimental or too use-case specific. It would be nice to have a complete story for supporting custom components. Today, all of the components use the component helper API which wraps internal framework details like runtime. However, there still isn't a very good story for loading custom components in the Angular frontend (e.g. ComponentRenderer's type to component map) and testing them.

Make it easy to get started with Mesop

Using Mesop today requires following our internal development setup which requires dependencies like Bazel/iBazel which makes it easy to interoperate with our downstream sync, but these dependencies aren't commonly used in the Python ecosystem. Eventually, I'd like make using Mesop as simple as pip install mesop and then using Mesop's built-in CLI: mesop serve for local development and mesop deploy to deploy on a Cloud service.

Areas of work:

  • Find a suitable ibazel replacement for Hot Reload. Instead of requiring Mesop developers to sync the entire repo and building the project with Bazel and iBazel, we should distribute a ready-to-use pip package of Mesop. However, this leaves an open question of how we support hot reload without iBazel which provides: 1) a filesystem watching mechanism and 2) live reload. We'll need to investigate good open-source equivalents for each of these capabilities.

  • Provide web-based interactive demos. Many JavaScript UI frameworks provide a playground (e.g. Angular) or interactive tutorial (e.g. Solid) so that prospective developers can use the framework before going through the hassle of setting up their own local dev environment. This would also be very helpful to provide for each component as it's a lot easier to understand a component by tinkering with a live example.

Explore power use cases

Today Mesop is good for internal apps with relatively un-stringent demands in terms of UI customizability and performance. For production-grade external apps, there's several areas that Mesop would need to advance in, before it's ready.

Areas of work:

  • Optimize network payload. Right now the client sends the entire state to the server, and the server responds with the entire state and component tree. For large UIs/apps, this can result in sizable network payloads. We can optimize this by sending deltas as much as possible. For example, the server can send a delta of the state and component tree to the client. In addition, if we use POST instead of GET, we can stop using base-64 encoding which adds a significant overhead on top of Protobuf binary serialization.

  • Stateful server. Even with the above optimizations, we'd essentially preserve the current architecture, but there's some limitations in how much improvements we can make as long as we assume servers are stateless. However, if we allow stateful servers (i.e. long-lived connections between the client and server), we can use things like WebSockets and always send deltas bi-directionally, in particular from client to server which isn't possible with a stateless server. The problem with this direction, though, is that it makes deployment more complex as scaling a WebSocket-based server can be hard depending on the cloud infrastructure used. In addition, we'll need to handle new edge cases like authentication and broken WebSockets connections.

  • Optimistic UI. One of the drawbacks for server-driven UI frameworks like Mesop is that it introduces significant latency to simple user interactions. For example, if you click a button, it requires a network roundtrip before the UI is (meaningfully) updated. One way of dealing with this shortcoming is by pre-fetching the next UI state based on a user hint. For example, if a user is hovering over a button, we could optimistically calculate the state change and component tree change ahead of time before the actual click. The obvious downside to this is that optimistically executing an action is inappropriate in many cases, for example, a non-reversible action (e.g. delete) should never be optimistically done. To safely introduce this concept, we could provide an (optional) annotation for event handlers like @me.optimistic(events=[me.HoverEvent]) so develpers could opt-in.

Some of these directions are potentially mutually exclusive. For example, having a stateful server may make optimistic UI practically more difficult because a stateful server means that non-serializable state could start to creep in to Mesop applications which makes undoing optimistic UI updates tricky

There's, of course, even more directions than what I've listed here. For example, it's technically possible to compile Python into WebAssembly and run it in the browser and this could be another way of tackling latency to user interactions. However, this seems like a longer-term exploration, which is why I've left it out for now.

Interested in contributing?

If any of this excites you, please reach out. The easiest way is to raise a GitHub issue and let me know if there's something specific you'd like to contribute.