Hey everyone, three months ago I started a side-project with the goal to create a beautiful user interface for the web version of our beloved LinkedIn. The idea was to enhance some javascript skills by building a smoothly transitioned and friendly interface that I, personally, would like to use when browsing LinkedIn.
First things first, here is the LIVE project and also the GitHub project.
As the goal here wasn't to design an UI, but to develop it using React.js, searching around I found an amazing redesign concept by Gregoire Vella that was pretty close to what I had in mind. Inspired by his work I coded the interface proposed. Here is a quick video of the final result:
I'm writing this article to share a quick overview of the development process, walking through some challenging parts, explaining some decisions I made on the way, some of the troubles and the learnings during the whole process. I'm hoping this article can help someone in some way.
The API
Development
Before jumping into the interface, the first task in my To-Do list was to create an API able to serve the data in the structure that I would need them. I didn't need to create it from scratch using a real database since it wouldn't be necessary to insert/update or delete any data — I just needed an API returning all the data that I would use. To achieve that, I used the awesome package json-graphql-server which does an amazing job creating a GraphQL API with static data that can be stored in a simple JSON file on the server — I just realize that the package name does a pretty good job describing it.
Problems?
The only inconvenience I had with the API was that json-graphql-server, unfortunately, could not easily handle a scenario where a collection refers to multiple items from another collection. For instance, a "Recommendation" system, where users can write a recommendation to a friend and also receive a recommendation from someone else. In this case, we would have the author and the target fields, both referring to the "Users" collection. This issue could be solved with an intermediate collection acting in the middle. Initially, this collection wouldn't be necessary, but apart from that, everything went well.
So, static GraphQL API as a back-end, done! To the UI!
The Interface
Development
React.js plays the main role here, using Next.js for File-system Routing, as well as SSR, Images Optimisation and a lot other advantages the framework provides us.
I would say that about 50% of the total time spent on this project was coding just the interface, creating all the display components, styling them with CSS Modules — where SASS could be used — making sure the components would still work on mobile devices, and so on... In the second week, I had to refactor some of the components from Class-based to Function-based components. At a certain point, I realize that React Hooks could easily handle all scenarios that would be necessary and there wasn't actually any real advantage for them to be created as javascript Classes. And also, Function-based components require less code, which is a plus for everyone.
With the all components created and working property, it was about time to integrate the app with our static API. In order to do that, Apollo Client was imported into the project to manage all the GraphQL requests the app would run. With Apollo in place, the pages could be created individually, requesting the data from the API, passing them to the child components, and rendering them. Even though Function-based components were the choice I made for the display components, the pages were kept as Classes to handle some complex scenarios with the infinite scroll functionality and conditional data fetching. No problem so far, just a lot of work.
Animations and Interactions
Development
No need to say that GreenSock is one of the most complete animation javascript library we have available today. The framework was used as the main source of animations that come directly from user interactions, like tabs, popups, drop-downs, etc.
Besides the user interactions, we also need to have smooth navigation between pages, to create a friendly user experience, and that's where Framer Motion API takes place in our LinkedIn. It has the ability to intermediate between Next router system applying CSS animations while leaving/entering a page. The implementation was quite easy, without any trouble... Except for the fact that it had a serious issue after building the project and testing it live.
Problems?
The problem here was that Next was creating a conflict with Motion API for some components down in the component tree from React — when a page was changed, Next core unmounted only the CSS Modules from some components too fast, not giving Motion API enough time for the page to fade-out of the screen, so the CSS was lost before the elements leave the page — the problem only happens after the project is bundled into static files, strangely enough, this behavior doesn't happen on Next development mode.
In fact, this is still an open issue at Next (by the time this post was written). Currently, there are some workarounds available to solve the problem, but they have their downsides as well. Fortunately, the problem drew a lot of attention at GitHub community, and hopefully, it will soon be fixed.
Learnings?
Working with animations that takes a big space at the device screen can be tricky sometimes. Targeting the right elements and choosing the right CSS properties is an important task to get a great performance. At first, it may not look a big deal, but it made a huge difference in the performance tests I ran with some old mobile and desktop devices.
There is also a second topic here. I wouldn't say it was a "problem" but more like a point of attention with the Framer Motion API integration. As some of the routes are dynamic generated based on data from the server, it is important to handle them with React Memo, where it can prevent components from unnecessary multiple renders. Otherwise, as soon as the router change was triggered — but before the animation — the current page would be re-render, not giving enough time for it to fade-out of the screen (again). These re-renders have a serious impact on the app's final performance, not only affecting the client-side of the application but also increasing the requests to the server leading to possible overloading problems. I would say that the memoization system when used wisely is an awesome optimization technique with a huge performance impact and deserves special attention while developing an application.
Data Management
Development
Working with individuals stand-alone display components fit most cases, but there are some scenarios that it's not enough to achieve a goal. The Chat component — which is composed of a master component and three sub-components — is a perfect example of that. The challenge here is not only the interface by itself — with a decent mobile version — but also to make the sub-components communicate with each other in harmony. At first, I thought of using Redux.js for that, but even though it would fulfill the requirements and solve our problem, I've chosen to work with React Context API instead, that is meant to share data that can be considered “global” for a tree of React components, fitting perfectly to the Chat component case. This wasn't the only place where Context API was required, but as mentioned, this is a "quick overview", so we are going to stick only with the Chat component.
Learnings?
React first introduced Context API in version 16 with the goal to solve the issue of props drilling where you avoid passing props through many components in the component tree. Using Redux, on the other hand, requires not only adding more libraries to the application bundle but also requires following a set of configurations and their boilerplates for the library to be able to manage the application states. Which doesn't mean that Context API replaces Redux and its purpose — to be honest Redux is perfect for larger applications where there are high-frequency state updates — but the point here is to understand the problem and balance the best solution for each case where sharable states are necessary.
Conclusion
Well, usually the side-projects that I decide to build end up taking me more time than I expected at the beginning, but overall the final result, in this case, was actually better than I expected as well, so I guess it's forgivable.
The development process should not be a blurry thing, but you don't need to know every single thing you will do beforehand. I divided the development process into individual steps here, only to create a clear structure for the article. These steps are usually merged with each other while developing, and sometimes you'll need to go back a few days and work on something you thought was completely done.
Start from the basics, recognize how the next step looks like, and work on it. Problems are inevitable and that's what makes each project unique in some way, and winning these small battles is one of the things that motivate us to go to the next one.
That's all everyone, if you have come this far, thank you for reading. And also, feel free to connect with me on LinkedIn (this time it's the real one).
Top comments (21)
I think the existing LinkedIn interface looks kinda nasty, too, but I suspect that's part of what they're going for. Businesses, banks, etc, which want to give the impression that they're Very Serious People like more old-school approaches. I think they think that anything modern-looking implies you're a new company and don't have much clout. What you're trying to do is make it look like a generic 202x social media site.
Now, LinkedIn is a poor experience, and I like your take on it much better, but you have decided to keep some of the less-good parts and even introduced some things which I feel are a step backwards.
In particular, you've gone for a very pale look where the contrast for a some parts of the interface is very low.
I also find things a little confusing. I don't like moving interfaces anyway, but the tabs confuse me because they slide in from the right no matter whether you're going left or right in the tab headings. My brain tells me that it's a slider, but it's not, and that feels off.
That menu in the top that says "discover"? I have no idea how to get that to change to "people" or "companies" or what have you. In fact, I don't know how to do anything except by drilling down into a company and a person then trying to navigate back up, or by using the global search and hoping I get a hit.
Don't take this as negative, I like what you're doing to "our beloved LinkedIn". Wait. Hold up. I don't think I've ever met anyone before who liked using LinkedIn. Is this a first?
Yeah I agree there, lol honestly as humans we don't like something that is too perfect because it'll look SUS so order to make humans come to the same spot you need to make a little bit of like a mistake so it looks normal, humans we are built solve problems mostly so if something is perfect we tend not to like it, {my own opinion}
That's awesome! Thanks for sharing.
May I ask how much time did you spend on the side project each day / week? Did you plan a weekly schedule and committed to it, or rather worked on it when you had some extra free time?
Hey Omri, 🍻. I can say for sure that it was at least 6 hours a week, but I'm also sure that it was way more than that... I had a small weekly (and flexible) schedule that I committed to, and also a goal to "not spend more than 3 days in a row without working on it". If I just decided to work on "extra free time" I would have taken a lot longer to finish. Planning usually helps me to hit the [start coding] button, and after that, seeing the progress kind of makes me keep going.
Got it, that's really great.
For me, I try working on side projects 5 days a week for 1-1.5 hours almost each day. I found that this is aa good balance between my free time and making real progress.
Keep on the good work Claudio 🍻
I also want to know this
This UI is just amazing. I can give you a tip. You can make chrome extension when people activate that extension it will give a new look to their LinkedIn. I'm sure many people hate the UI of LinkedIn.
Hey Claudio,
I like it a lot! I noticed a few things while playing around with it though. First, some of the text in the company header can be hard to read if the image has white in it. I saw this on the RedHat page, so perhaps adding more contrast would help. I put a screenshot below. Also on that page, Careers is spelled wrong.
Overall, it looks really good and offers a refreshing take on a platform that can sometimes feel clunky and outdated. Well done! 🍻
Good eye, Tim. Thanks, glad you liked it. 🍻
Nice work!
I've been studying Framer Motion. It's nice to see what you have done with it
Nicely done!
Awesome, I had the same issue making an animation to my Next pages. I was reading eagerly to know how you made it then got the dead end lol
You got yourself a new follower
Looks amazing! Great work. It is much cleaner and easier to read.
nice work, loved it & thanks for sharing.