Marvel • 2022

Marvel is a Makerspace/Lab in UVCE. The lab just got started when I was in my 2nd year of college, with the goal of providing the students, the space and support to collaborate and build cool stuff. It came out with a bunch of programmes to get the students involved. And, there was the need for a webapp to make these programmes happen. My work with marvel began here.

Today, hundreds of students use the webapp to document and showcase their course works and project works. It has user profiles, access management over resources, a review system, event pages for when the lab conducts events, and a logo.

Lessons in building a Product

During the continous and iterative process of building and maintaining the product, I learnt quite a few things and this article is my attempt to summarize that journey and point out a few key leanings.

Early Ideas

When we were starting out, we didn't have a very clear idea on what the webapp was exactly supposed to do. But the basic idea was that students would submit/showcase reports on tasks they perform. And, These reports should be reviewed by one of the coordinators. The tasks were divided into levels and were part of a particular domain of study. There were 5 domains of study at the time (IOT, Cloud Computing etc.,) and each domain would have a set of coordinators.

I modelled the first iteration of the product around the keywords highlighted above. Some drawings I made to explore basic layout of some screens are shown below.

Early Ideas


And with that, I started building for the first release. I chose MERN stack with Azure CosmosDB (MongoDB API). Frontend was a React SPA that's fully rendered fully on the client-side (this was a mistake and we'll come back to it later). It was hosted on Azure Static Webapps (a CDN). The backend was an Express JS REST API that handled Authorization, and exposed the database. It was hosted on Azure App Service.

Other services like Cloudinary (for image hosting), Google OAuth, Sendinblue (for transactional emails), Microsoft Clarity (for analytics) were also used.

Why Azure?

Azure has a generous free tier, that best suited our estimated workloads at the time. And, having the database, backend, Frontend all under a single platform meant that we could conviniently manage all of them from a single portal. It worked very well for us. CDN was fast, database queries were almost instant. Features like continous backup and migration were available for free. Other features like budgeting and setting up alerts were very helpful.

A few Screenshots from the first version of the app are shown below.

DashboardEditorProfile PageCourse PageCourse Page in edit modeArticle Page

react-markdown was used along with sanitize-html (to prevent XSS attacks) to render markdown with custom react components. HTML was allowed in markdown to let the users embed iframes from trusted sources. react-query was used to manage queries from the client side. Caching, Pagination, periodically refreshing queries, and programmatically invalidating specific queries, all that was super convinient with react-query.

Problems and code debt

The webapp worked very well. The lab quickly adopted it into it's programmes and the students found it intuitive to navigate the app and get stuff done. everybody was happy :).

But as the lab introduced new programmes, and changes to existing ones, the scope of the application grew. We kept adding more and more features and reached a point where adding new features along side existing ones just didn't cut it.

Technical limitations from the stack that was being used and logical limitations from the way things were structured meant that we needed a massive re-write.


It was time for us to take a hard look at the core problem we were trying to solve and simplify the product to its core essence. This meant that we needed a deeper understanding of what we actually wanted in the first place.

A New Model

After a few discussions with our stakeholders, we were able to simplify the problem and come to few conclusions.

What do the people in lab do?

well, they do a lot of stuff but we can call all of that as some kind of work.

The idea of work

This newly found abstraction had low barriers and high ceilings. It kept the simple things simple and made the complex things possible. People could be part of multiple works at the same time, irrespective of their roles. And, Roles and Permissions could be managed atomically at each atomic object, which is the work.

Technical & Design changes

Better DX and Maintainability.

We migrated to a Monorepo architecture (Turborepo) that mainly housed our Webapp, Storybook for our Design System, and our UI library. We started adopting Typescript and tools that worked well with Typescript, like Prisma. and TailwindCSS for styling. Modelling relations in NoSQL is hard. It can make the database vulnerable to inconsistencies. So we migrated to MySQL.

Better SEO, Faster Loadtime, and Open Graph.

We migrated to Next.js 13. Parts of the UI that had content required for SEO was rendred on the server and the interactive parts of the UI were rendered on the client. This reduced the amount of client-side javascript and improved performance. Features like Open Graph link previews were now possible. We were able to dynamically generate and cache link preview images on the fly for crawlers.

A new Design System.

We were previously using Material UI with slight customisation and it worked fine. But we had reached a stage where we needed more control over Design and Branding accross the apps. And, we needed components that supported SSR with Next.js 13 (with "use client" directive). So we built our own Design system with deliberate choice of primitives like type and color. Components were built with accessibility as a requirement using Adobe's react-aria.

Screenshots of some of the screens from the new webapp are shown below.

LandingLanding - dark modeMenusearchprofilecourse workproject workroles managingblog pageEvent page

Some Screenshots in Mobile view

Event page phoneevent page phone 1events phoneblog phone

Open Graph Link Previews

A significant part of the traffic for the webapp came from messaging apps and social apps. When sending a broadcast message in the college community groups, it was important to create a good impression to convert views into clicks. So we designed link preview images that could be dynamically generated based on the content.

Some of the link preview images (as they appear on WhatsApp Android) are shown below.



With all the efforts put in to improve so many aspects of the product, we were able to successfully achieve the goals we set out to achieve.


Getting huge numbers from Google Search wasn't really our goal as the webapp was mostly meant for internal use within the college community. But, metrics like these mean that 100% of the pages are performant, indexable and have good experience on mobile with little to no layout shifts or weird sizing issues.

A low number of pages per session and a high scroll depth percentage shows that users were able to quickly find what they were looking for, without having to navigate to too many pages inbetween.


I learnt that building more features doesn't neccessarily get you close to solving the problem. A lot of the times, a "faster horse" isn't exactly what's needed. It's very easy to get stuck around a local maxima, where marginal improvements don't mean much. The problem at hand can keep changing and we'll have to make conscious attempts to understand it deeply.

I learnt that we need to build systems or solutions in such a way that it has low barriers and high ceilings. This is possible when we have a deep understanding of the problem, and we're able to simplify and generalize the problem as a concept. A relevant quote here would be, "Simplifying doesn't mean removing things. It means distilling something to its core essence." - Brian Chesky. To do this, we'll have to know what the core essence is.

And, I learnt that extensively researching the toolset before starting to build something is very important. Picking the right tools can make you more productive, save time, and enable capabilities that wouldn't be possible with a tool that's not relevant for the job. An ideal senario is where you can spend more time solving the problem and less time fiddling with the medium or the tools.

Thanks for reading ✨. Let me know what you think.