A Beginner’s Guide to Setting Up a Project in Laravel

Original Source: https://www.sitepoint.com/laravel-project-setup-beginners-guide/?utm_source=rss

A Beginner's Guide to Setting Up a Project in Laravel

In this Laravel tutorial, you’ll learn about the building blocks of Laravel and how to use it to set up a small project.

Continue reading
A Beginner’s Guide to Setting Up a Project in Laravel
on SitePoint.

How to Create Content in WordPress with AI

Original Source: https://www.sitepoint.com/wordpress-create-content-ai/?utm_source=rss

How to Create Content in WordPress with AI

Learn how to install and use the AI Bud WordPress plugin, a powerful AI tool for simplifying your WordPress content creation process.

Continue reading
How to Create Content in WordPress with AI
on SitePoint.

How to Deploy Apache Airflow on Vultr Using Anaconda

Original Source: https://www.sitepoint.com/deploy-apache-airflow-vultr-anaconda/?utm_source=rss

How to Deploy Apache Airflow on Vultr Using Anaconda

Learn how to deploy an Airflow app in a Conda environment and secure the app using Nginx and request SSL certificate from Let’s Encrypt.

Continue reading
How to Deploy Apache Airflow on Vultr Using Anaconda
on SitePoint.

Transforming The Relationship Between Designers And Developers

Original Source: https://smashingmagazine.com/2024/05/transforming-relationship-between-designers-developers/

In the forever-shifting landscape of design and technology, some rare artifacts surprisingly never change.

Throughout the last two decades, we have witnessed the astonishing evolution of creative tooling, methodologies, and working practices. However, after all of this advancement, we still have clients asking to make the logo bigger, designers despairing as their creations are built with not quite the exact amount of bottom-margin, and developers going crazy about last-minute design changes.

Quite frankly, I’ve had enough. So join me in a parenting-style-hands-on-hips pose of disdain, roll up your sleeves, and let’s fix this mess together, once and for all!

Why Is This Still An Important Topic?

Ultimately, the quality of your designer-developer relations will have a vital impact on the quality of your product. In turn, this will impact customer experience (be it internal or external).

Customer experience is everything, and these days the smallest of chinks can create an even bigger dent in the business itself.

It may not even be an obvious or noticeable issue. Over time, those moments of misunderstanding in your team could result in a series of micro-inconsistencies that are felt by the customer yet sneak underneath the radar of quality assurance.

Perhaps you’ll catch these things during user research, but in this scenario, you’d be playing catch-up instead of advancing forward.

To cut a long story short, it could be slowing you down in the race against your competitors and costing you more money in the process.

So, with that in mind, let’s get stuck into the techniques that can steer us in the right direction and inspire everyone on the team to deliver the slickest of user experiences together.

Working Culture

In my opinion, process improvements may only get you so far. The working culture in your organization will heavily influence the output of your digital teams. Whilst the subject of culture is incredibly vast, there are a few key elements that I think are hugely important to foster a greater level of collaboration between design and developers:

Alignment on the goals of the project and/or business.
Encouraging a more “robotic” attitude to feedback. Of course, you can be passionate about what you do, but when it comes to feedback, I always try to encourage people to respond with logic before emotion.
Communication: Ultimately, you have to trust people to be proactive. You can have a great process, but the gaps and edge cases will still slip through the net unless you have people who are open and ready to prod each other when issues arise.

This may seem like common sense to many of us, but many organizations (big ones, too!) still operate without this crucial foundation to motivate and support their teams.

However, it is essential to be honest with yourself and consider the role you play within your team. Even if you think you have already fulfilled these criteria, I’d encourage you to investigate this further to ensure everyone feels the same. It can be as simple as having a 121 discussion with each member of the team, or you could even send out short questionnaires to gauge your workplace’s suitability for an optimal designer and developer collaboration.

You might be surprised by what you hear back from people. Treat any criticism as gold dust. It’s an opportunity to improve.

Once you’ve created this foundation within your organization, it’s important to maintain and protect it. Keep reviewing it regularly, and make sure that anyone joining the team will be able to fit in. This leads us nicely on to…


If you’re scaling your team, maintaining quality can always be a challenge as you grow. Despite the challenges, it’s important to continue hiring people who have a positive and empathetic attitude to ensure you can maintain this foundation within your workplace.

In order to gauge this, I would like to include the following interview questions.


Begin by showing a sample screenshot of your product or a specially crafted concept design:

“You’ve just built X, and the designer wants to change Y. How do you respond?”

Follow up:

“The designer and PM reject your suggestion because of ___. How do you respond?”


Begin by showing a sample screenshot of your product or a specially crafted concept design:

“The developer says, “We can’t build X quickly; can we do Y instead to deliver faster?” How do you react?”

Follow up:

“The product owner says they are then disappointed with the design. How do you react?”

I recommend asking these kinds of questions in the middle or towards the end of the interview so you have already built rapport. If the candidate is at ease, they are more likely to let slip any negative attitudes that lurk beneath the surface.

I’ve asked interview questions like these to many designers and developers, and every so often, they will openly criticize and stereotype each other with a smile on their faces. I’ve even seen some candidates become visibly frustrated as they recount real-life scenarios from their own experiences.

How you score this is more difficult. Ultimately, skills and work ethic are the most important things, so concerning answers to these questions may not necessarily lead to an outright rejection but perhaps flag something you may need to work on with the candidate if they do later join your team.

Hopefully, in most cases, the stronger candidates you speak to will naturally provide balanced and conscientious responses to these tests of character!


We talked a bit about hiring, but I’d imagine many people who need this article are more likely to be in the midst of a designer-developer flame-war as opposed to trying to prevent one in the future!

So, what can we do process-wise to keep things flowing?

Provided that there is plenty of early and ongoing collaboration in your workflow, there is no absolute right or wrong answer. It’s about what fits your team and your product best. Ultimately, you need to discard the silos of the past and start working together as a team early on.

Developers would typically be the last people to get involved, but they should be involved from the start to guide technical feasibility and provide their own ideas.
Designers are often more involved in the beginning but can often drift away before the end of a release. However, we need to keep them onboard and get them to play with the product so we can keep making it even better!

It’s important to be open-minded about the solutions. Alas, I have even worked in organizations where different teams have different approaches. Bearing that in mind, here are some good places to start in terms of exploring what might work for your workplace.


When new features are on the horizon, getting everyone involved in these discussions is crucial.

Sometimes, it can be difficult for developers to detach from the current sprint and think ahead, but it’s important that we have their guidance, and it is ultimately going to save them (and the whole team) time further down the line.

Scoping can appear in many different forms across the spectrum of agile methodologies out there. It’s not my intention to cover any of these and discuss all the positives and negatives of each (that’d make this into a book, and not one that anyone would like to read!); in fact, I am deliberately not mentioning any of them. This article is ultimately about people, and the people we need at this early stage are not just the stakeholders and a product manager. We need designers and developers shaping these early discussions for the following reasons:

They will bring their own ideas.
They will visualize the idea very quickly and assess its feasibility.
They will connect the concept with other parts of the domain.
They will also (albeit rarely!) prevent an impossible dream or daft idea from growing on the face of the business like a festering wart.

Another Perspective On Scoping: SquaredUp

In order to take a deeper dive into the subject of scoping, I spoke to Dave Clarke, product manager at SquaredUp.

“Developers are looped in during the design stage, and we’ll test interactive mockups with the engineering team as well as other internal stakeholders before going out to external audiences for feedback. This means that when a feature is ready to be built by an engineer, they’re already really familiar with what we’re building”

— Dave Clarke

Back in late 2018, I met the SquaredUp team at an open day in their UK hub in Maidenhead. I was impressed by the quality of their product, considering it was a very technical audience. It looked beautiful, and you could tell that they went the extra mile in terms of collaboration. Not only do they involve developers in the design phase, but they get them involved even earlier than that.

“We send engineers to events so they can talk to customers and hear their pain points first-hand. This helps foster a real appreciation and understanding of the ‘user’ and ensures designers/developers/PMs are all coming at a problem with a solid understanding of the issue from the user’s perspective.”

— Dave Clarke

This brings us back again to that all-important foundation. Alignment on goals is key, and what better way to reinforce that message than by getting everyone involved in hearing directly from the end users of your product?

Design Presentations

Once the wheels are in motion on the big new thing, many teams like to have the designer present their work for forthcoming iteration(s) to the team. This allows everyone to have a say and get excited about what is coming up.

Once again, there are many organizations that would simply agree on the design between stakeholders and designers alone. From the developer perspective, this is incredibly frustrating. Not only will it result in a lower-quality output, but it will also make developers feel as though their opinion doesn’t matter.

With my developer hat on, though, I absolutely love these kinds of sessions. They allow us to question the details, suggest alternatives, and consider how we slice stuff up into smaller bundles of value that can be released faster.

With my design hat on, it caters to my need to think about the bigger picture. It’s not always practical to design iteratively, but in these sessions, we can all get together and appreciate the end-to-end experience.

Typically, we allow the designer time to talk through everything, allowing for questions throughout, and give everyone a chance to dive in and bring their ideas to the table. However, do what works for your team. If you have a designer who wants to present, take all questions at the end and then make changes afterward, do that. If you have one who likes handling lots of questions throughout and makes changes live, go with that.

Perhaps even give it your own identity, too. In my current workplace, one of the squads calls it Design Time and in our squad, we decided to open the name to a poll, and thus (with one cheeky addition to the poll from a colleague) the Itty Bitty Refinement Committee was born!

Managing Conflict

However, these kinds of sessions do have the potential to get sidetracked. So, as with any meeting, it is essential to have a clear agenda and ensure that good facilitation prevents things from going off-piste. If there are conflicts, I always try to find resolutions by considering where we might find the answers. For example,

Can we look at our analytics?
Which option is a better fit for our company goals?
Could we do an A/B test to see what is more effective?

When people bring ideas to the table, it’s always important to acknowledge them positively and seek further exploration. Sometimes, we can agree on an approach quickly, and on other occasions, we can defer the discussion to a later refinement session.

Sharing Responsibilities

In my opinion, there is also a gray area between designers and developers, where it often isn’t clear who holds responsibility. This is a big risk because, in many organizations, essential aspects can be completely forgotten.

From my past experience, there are two key areas where I see this happening often. So this may not be exhaustive, but I encourage you to think about these and then ask yourself: Is there anything else — specific to my organization — that could have fallen into this void between our designers and developers?

See if you can identify these risks and agree on a way of working together to ensure they are tackled effectively.


Nowadays, many dev teams are working on JavaScript-heavy applications, and most of us will have the power of CSS transitions at our disposal. Yet, I frequently land on new projects where they aren’t being leveraged to enhance the customer experience.

Animations can be quite time-consuming to create using many design tools. In particular, I often find that loading states are quite fiddly to prototype in some cases.

In my recent work at Floww, I collaborated with designer Hidemi Wenn on an animated progress bar. For the first version, Hidemi had begun with an idea crafted in After Effects. I replicated this in a CodePen and suggested adding some bubbles to highlight the changes in the numbers.

Note: Of course, CodePen is just one example of this. There are many other tools out there, such as Storybook, that can also allow us to build and collaborate on ideas quickly.

See the Pen Bar Chart of Destiny [forked] by Chris Day.

This allowed Hidemi to see her creation working in the browser early — before it had been fully implemented into the product — and we then collaborated further to make more enhancements.

“Working together like this was awesome! We could easily bounce around ideas, and tweaking the animation was a breeze.”

— Hidemi Wenn, Product Designer at Floww

Pairing is often between developers, but why not jump on a call and pair with a designer whilst you write the CSS? This gives them full transparency, and you can collaborate together.

Nowadays, we have amazing tools at our disposal to collaborate, and yet still, so many designers and developers elect to operate in silos.


One of the first things I do when joining any existing digital project is to spin up Wave (an accessibility testing tool) and subsequently slump into my seat in despair.

Accessibility is something that always suffers as a result of a designer/developer standoff. Some might say it’s the realm of design, while others would argue it’s quite a technical thing and, therefore, lives in dev land. The truth is it is a shared responsibility.

Take something like :focus, for example. Whenever I review code, this is something I always check and often discover it’s missing. Ask the developer, and they’ll say, “We didn’t have designs for it.” Well, perhaps, ask the designer to create them, just as I’d expect the designer to query an unimplemented state they had designed for.

We should scrutinize each other’s work and continue to channel our inner robot to respond with logic when it comes to constructive criticism. Keep encouraging everyone to embrace feedback because that is the gold dust that makes our product shine brighter.

During Implementation

Having steered our way together through the implementation of our features, at some point, we begin to approach the time to release our features into the wild. We are on the final stretch, and thus, it’s time for developers to stage a reverse-design presentation!

Whilst mentoring developers on this subject, I always remind them not to take the feedback personally.

Likewise, I ask designers to never hold back. Be persnickety (in a kind way!) and ensure all your concerns are addressed.

It’s only natural for a developer to behave defensively in these scenarios. As a result, designers may hold back on some of the feedback they provide in order to prevent upsetting the developer.

Developers are often very vocal, and if you are tasked with delivering a barrage of design feedback to them, it can appear daunting and make designers fearful of a backlash.

Prevent the silo. Perhaps have a third party, such as the product owner/manager, attend the meetings. They can diffuse any situation by referring us all back to the business value.

I’ve also witnessed rare cases where the developer has nodded and agreed with all the feedback and then just hasn’t implemented any of it afterward! So, make sure it’s all captured in whatever project management tools you use so you can follow up on the status. Sometimes, it’s easy to forget to do this when the changes are so small, so often (in my current team), we might create a single ticket on our board to implement all the feedback changes as opposed to creating a work item for each.

Another common issue I’ve found is that I’ve met many designers who don’t actually ever test out the products that they design. For me, they are missing out on the opportunity to further hone their work, and to learn.

If you’re a designer, ensure that you can log in to the app/website. Get a test account from someone, and try to break stuff!

Once all the feedback is in, we can create more work items to give our product those magical finishing touches and ship our masterpiece to the World.

Design Systems

Having mentioned focus states earlier on, you were probably already thinking about design systems before this heading came along! Of course, the design system plays a key role in helping us maintain that consistency, and ensuring accessibility concerns are baked-in to our library of beautiful components.

There are many, many articles about design systems out there already but here, I am going to just consider them in the context of the working relationship.

As the design system encourages reuse, it encourages us to think about other teams in our organization and be more mindful.

If the basic building blocks are covered, we can focus on solving more complex challenges together. I think this is also a really important value to get your teams on board with.

Design systems can also cause friction. Not everyone will get on board with it. Some designers will feel as though it restricts their creativity. Some developers will be frustrated at having to update the design system instead of cracking on with their own features.

In my opinion, these attitudes will not only slow you down but could harm the working culture of your business. Nowadays, I’d say it’s absolutely crucial for any product team (big or small) to have a design system and have the majority of your team buying into it.

I’ve been present at organizations where the design system is neglected, and in these cases, it actually ends up worse than not having one at all. You really need the majority of your team to be committed to it; otherwise, some people will go off-piste and keep reinventing the wheel (probably without those focus states!).

Another Perspective On Design Systems: GOV.UK

The GDS (Government Digital Service) of the UK has built a design system that serves a vast spectrum of different services and tech stacks. An enormous challenge, which is almost certain to be of interest in our quest for knowledge! So, I got in touch with product designer Ed Horsford who has worked on a series of government services that make use of this.

“GDS provides the GOV.UK Prototype Kit, so as a designer, I can create something in the kit, make full use of the functionality of the design system, and point developers towards the prototype.”

— Edward Horsford

Whilst many other organizations are now making use of tools such as Figma’s excellent Dev Mode feature to streamline design handover, this still requires naming conventions to be lined up between the codebase and the Figma component library. What’s impressive about GDS’ approach here is that the provision of their own prototyping tool makes it absolutely clear to developers which components need to be used. However, the availability of a great design system tooling doesn’t always guarantee a smooth outcome, as Ed explains:

“It can be a bit of a mind-shift for developers new to the UK government or using design systems in general — they may default to hand coding the HTML and CSS to match a design, rather than using the components from the design system to match the prototype.”

“If there is a bespoke requirement outside of the design system, then I will always call it out early so I can discuss it with the team.”

— Edward Horsford

Once again, this takes us back to the importance of communication. In a landscape where a design system must be deployed amongst many different teams, it’s up to the designers and developers to scrutinize each other’s work.

It was great to hear that as a designer, Ed was actively looking at the front-end code to assist the developer, ensuring the design system was respected so that all of its many benefits could be embedded into the product.

Crisis Mode

I appreciate that much of the advice in this article requires planning and a fair bit of trial and error. So what do you do if your designers and developers are already engulfed in a mass brawl that needs to be quelled?

In these scenarios, I think it is an ideal moment to pause and simply ask each member of the team: What is our goal? What are we working towards?

If people are angry, in some ways, it’s a good thing because you know they care. People who care should always be open to a bit of a reset. Openly discuss what everyone wants, and you’ll probably be surprised at how aligned people really are; I always go back to this fundamental and work onwards from there.

Sometimes, we get so tangled up in the details we forget what is truly important.


For every angry team, there are probably many more that just don’t give a crap. For me, this is a far worse situation.

Every problem described in this article could be present. The designers make mockups, the designers build them without question, and everyone gets paid. Who needs to question anything? It’s just a job, right?

Can we really fix this?

Well, in my opinion, you are going to need a much deeper dive into company culture to try and revive that team spirit. I have worked at places like this in the past, and it is very challenging to try and implement solutions when the people are just not bought into the vision of the organization.

Whether this is feasible or not depends on your role and the organization itself. I have walked away from situations like this in the past because I didn’t feel as though the organization was willing to change or even be able to acknowledge the problem.


The dynamic between designers and developers is a subject that has always been of great interest to me, as I’ve worked in both roles as well as being an agency owner.

I’m confident as the years continue to progress, this will become less of a problem as the world of work continues to gravitate towards greater levels of inclusivity, honesty, and openness. The foundations of great company culture are so crucial to ensuring that designers and developers can unite and take on the world side-by-side on behalf of your organization.

For now, though, in today’s fragmented and divided world, you can gain a true competitive advantage by leveraging the power of a harmonious digital team built on the foundations of your organizational values.

Go smash it!

Why Is My Printify Order On Hold?

Original Source: https://ecommerce-platforms.com/articles/why-is-my-printify-order-on-hold

After an order is placed with Printify, the system will provide status updates as the product passes through the pre-production phase to production and shipping–and until it reaches the customer.

When an order is ‘on hold,’ it means production has not started. The hold may be due to the order not being completed and submitted, or that there is an issue that requires attention.

Order Statuses Explained

Any time you place an order on a print-on-demand platform (e.g. Printify or Printful), you can check the platform at any time to confirm the status of the order. With Printify, the possible order statuses you might encounter are:

Pre-production statuses:

On hold: Submit order

Sending to production

On hold: Action required

Production statuses:

In production

Has issues

Canceled: Canceled by Print Provider

Canceled: Various

Shipping statuses:

Ready to ship


On the way

Available for pickup

Out for delivery

Delivery attempt

Shipping issue

Return to sender


An ‘on hold’ status can happen during the pre-production stage.

A Closer Look at Pre-Production

Before an order is sent to one of Printify’s print providers, the system will verify that all necessary information was entered correctly, payment was processed, the products are available, no claim to intellectual property was filed, and that Printify vendors can deliver to the address provided.

If there is an issue and you have Printify Premium benefits, you can contact Printify Connect. This is a customer-support program that handles issues related to orders connected to your Premium account.

More About ‘On Hold: Submit Order’

Depending on the order approval settings of your account, the order may be automatically submitted or held for a designated period before being sent to Printify.

When you create an order manually, you can also submit it immediately or wait. During either of these scenarios, the order status will show as ‘On Hold: Submit Order.’

When an order is on hold, you can edit it (e.g., quantity, color, etc.) before submitting it. After submitting, the order status should be updated within a few minutes.

If it doesn’t show as ‘Sending to Production’ after thirty minutes, contact the Printify Support Team to ensure it went through correctly.

More About ‘On Hold: Action Required’

If you see this status pop up on an order, there is a problem. Check the sub-status for more information about what the issue is and how you can rectify the situation. Here are the possible reasons for an ‘On Hold: Action Required’ status:

Payment not received: Set up a payment method and ensure enough funds are available. Resubmit the order. If it happens again, try another payment method.

Out of stock: Cancel the order or select a replacement product or print provider.

Discontinued product: Cancel the order or select a replacement product or print provider.

Address issues: Correct the address and resubmit the order.

Canceled – IP reported: This status means your product was flagged as infringing on someone else’s intellectual property. You can remove the product in question and resubmit the rest of the order (if there is more). If your product is unique and you think it should not be flagged in error, submit an appeal with Printify.

Shipping restrictions apply: There are some locations in which Printify vendors can not deliver products.

What Happens Next?

After the ‘on hold’ status is removed, the order will be sent to production. If you are curious about how your experience stacks up against other print-on-demand platforms, read the reviews posted by ecommerce-platforms.com.

We are committed to helping entrepreneurs grow their businesses by rigorously evaluating online software solutions and providing unbiased advice.

Wondering whether Printify shipping is expensive? Be sure to read our latest post!

The post Why Is My Printify Order On Hold? appeared first on Ecommerce Platforms.

"Make something people want to steal," 7 tips for better menu design

Original Source: https://www.creativebloq.com/features/menu-design-tips

How to make your menu more enticing, plus why your menu needs to work on mobile.

The Forensics Of React Server Components (RSCs)

Original Source: https://smashingmagazine.com/2024/05/forensics-react-server-components/

This article is a sponsored by Sentry.io

In this article, we’re going to look deeply at React Server Components (RSCs). They are the latest innovation in React’s ecosystem, leveraging both server-side and client-side rendering as well as streaming HTML to deliver content as fast as possible.

We will get really nerdy to get a full understanding of how RFCs fit into the React picture, the level of control they offer over the rendering lifecycle of components, and what page loads look like with RFCs in place.

But before we dive into all of that, I think it’s worth looking back at how React has rendered websites up until this point to set the context for why we need RFCs in the first place.

The Early Days: React Client-Side Rendering

The first React apps were rendered on the client side, i.e., in the browser. As developers, we wrote apps with JavaScript classes as components and packaged everything up using bundlers, like Webpack, in a nicely compiled and tree-shaken heap of code ready to ship in a production environment.

The HTML that returned from the server contained a few things, including:

An HTML document with metadata in the <head> and a blank <div> in the <body> used as a hook to inject the app into the DOM;
JavaScript resources containing React’s core code and the actual code for the web app, which would generate the user interface and populate the app inside of the empty <div>.

A web app under this process is only fully interactive once JavaScript has fully completed its operations. You can probably already see the tension here that comes with an improved developer experience (DX) that negatively impacts the user experience (UX).

The truth is that there were (and are) pros and cons to CSR in React. Looking at the positives, web applications delivered smooth, quick transitions that reduced the overall time it took to load a page, thanks to reactive components that update with user interactions without triggering page refreshes. CSR lightens the server load and allows us to serve assets from speedy content delivery networks (CDNs) capable of delivering content to users from a server location geographically closer to the user for even more optimized page loads.

There are also not-so-great consequences that come with CSR, most notably perhaps that components could fetch data independently, leading to waterfall network requests that dramatically slow things down. This may sound like a minor nuisance on the UX side of things, but the damage can actually be quite large on a human level. Eric Bailey’s “Modern Health, frameworks, performance, and harm” should be a cautionary tale for all CSR work.

Other negative CSR consequences are not quite as severe but still lead to damage. For example, it used to be that an HTML document containing nothing but metadata and an empty <div> was illegible to search engine crawlers that never get the fully-rendered experience. While that’s solved today, the SEO hit at the time was an anchor on company sites that rely on search engine traffic to generate revenue.

The Shift: Server-Side Rendering (SSR)

Something needed to change. CSR presented developers with a powerful new approach for constructing speedy, interactive interfaces, but users everywhere were inundated with blank screens and loading indicators to get there. The solution was to move the rendering experience from the client to the server. I know it sounds funny that we needed to improve something by going back to the way it was before.

So, yes, React gained server-side rendering (SSR) capabilities. At one point, SSR was such a topic in the React community that it had a moment in the spotlight. The move to SSR brought significant changes to app development, specifically in how it influenced React behavior and how content could be delivered by way of servers instead of browsers.

Addressing CSR Limitations

Instead of sending a blank HTML document with SSR, we rendered the initial HTML on the server and sent it to the browser. The browser was able to immediately start displaying the content without needing to show a loading indicator. This significantly improves the First Contentful Paint (FCP) performance metric in Web Vitals.

Server-side rendering also fixed the SEO issues that came with CSR. Since the crawlers received the content of our websites directly, they were then able to index it right away. The data fetching that happens initially also takes place on the server, which is a plus because it’s closer to the data source and can eliminate fetch waterfalls if done properly.


SSR has its own complexities. For React to make the static HTML received from the server interactive, it needs to hydrate it. Hydration is the process that happens when React reconstructs its Virtual Document Object Model (DOM) on the client side based on what was in the DOM of the initial HTML.

Note: React maintains its own Virtual DOM because it’s faster to figure out updates on it instead of the actual DOM. It synchronizes the actual DOM with the Virtual DOM when it needs to update the UI but performs the diffing algorithm on the Virtual DOM.

We now have two flavors of Reacts:

A server-side flavor that knows how to render static HTML from our component tree,
A client-side flavor that knows how to make the page interactive.

We’re still shipping React and code for the app to the browser because — in order to hydrate the initial HTML — React needs the same components on the client side that were used on the server. During hydration, React performs a process called reconciliation in which it compares the server-rendered DOM with the client-rendered DOM and tries to identify differences between the two. If there are differences between the two DOMs, React attempts to fix them by rehydrating the component tree and updating the component hierarchy to match the server-rendered structure. And if there are still inconsistencies that cannot be resolved, React will throw errors to indicate the problem. This problem is commonly known as a hydration error.

SSR Drawbacks

SSR is not a silver bullet solution that addresses CSR limitations. SSR comes with its own drawbacks. Since we moved the initial HTML rendering and data fetching to the server, those servers are now experiencing a much greater load than when we loaded everything on the client.

Remember when I mentioned that SSR generally improves the FCP performance metric? That may be true, but the Time to First Byte (TTFB) performance metric took a negative hit with SSR. The browser literally has to wait for the server to fetch the data it needs, generate the initial HTML, and send the first byte. And while TTFB is not a Core Web Vital metric in itself, it influences the metrics. A negative TTFB leads to negative Core Web Vitals metrics.

Another drawback of SSR is that the entire page is unresponsive until client-side React has finished hydrating it. Interactive elements cannot listen and “react” to user interactions before React hydrates them, i.e., React attaches the intended event listeners to them. The hydration process is typically fast, but the internet connection and hardware capabilities of the device in use can slow down rendering by a noticeable amount.

The Present: A Hybrid Approach

So far, we have covered two different flavors of React rendering: CSR and SSR. While the two were attempts to improve one another, we now get the best of both worlds, so to speak, as SSR has branched into three additional React flavors that offer a hybrid approach in hopes of reducing the limitations that come with CSR and SSR.

We’ll look at the first two — static site generation and incremental static regeneration — before jumping into an entire discussion on React Server Components, the third flavor.

Static Site Generation (SSG)

Instead of regenerating the same HTML code on every request, we came up with SSG. This React flavor compiles and builds the entire app at build time, generating static (as in vanilla HTML and CSS) files that are, in turn, hosted on a speedy CDN.

As you might suspect, this hybrid approach to rendering is a nice fit for smaller projects where the content doesn’t change much, like a marketing site or a personal blog, as opposed to larger projects where content may change with user interactions, like an e-commerce site.

SSG reduces the burden on the server while improving performance metrics related to TTFB because the server no longer has to perform heavy, expensive tasks for re-rendering the page.

Incremental Static Regeneration (ISR)

One SSG drawback is having to rebuild all of the app’s code when a content change is needed. The content is set in stone — being static and all — and there’s no way to change just one part of it without rebuilding the whole thing.

The Next.js team created the second hybrid flavor of React that addresses the drawback of complete SSG rebuilds: incremental static regeneration (ISR). The name says a lot about the approach in that ISR only rebuilds what’s needed instead of the entire thing. We generate the “initial version” of the page statically during build time but are also able to rebuild any page containing stale data after a user lands on it (i.e., the server request triggers the data check).

From that point on, the server will serve new versions of that page statically in increments when needed. That makes ISR a hybrid approach that is neatly positioned between SSG and traditional SSR.

At the same time, ISR does not address the “stale content” symptom, where users may visit a page before it has finished being generated. Unlike SSG, ISR needs an actual server to regenerate individual pages in response to a user’s browser making a server request. That means we lose the valuable ability to deploy ISR-based apps on a CDN for optimized asset delivery.

The Future: React Server Components

Up until this point, we’ve juggled between CSR, SSR, SSG, and ISR approaches, where all make some sort of trade-off, negatively affecting performance, development complexity, and user experience. Newly introduced React Server Components (RSC) aim to address most of these drawbacks by allowing us — the developer — to choose the right rendering strategy for each individual React component.

RSCs can significantly reduce the amount of JavaScript shipped to the client since we can selectively decide which ones to serve statically on the server and which render on the client side. There’s a lot more control and flexibility for striking the right balance for your particular project.

Note: It’s important to keep in mind that as we adopt more advanced architectures, like RSCs, monitoring solutions become invaluable. Sentry offers robust performance monitoring and error-tracking capabilities that help you keep an eye on the real-world performance of your RSC-powered application. Sentry also helps you gain insights into how your releases are performing and how stable they are, which is yet another crucial feature to have while migrating your existing applications to RSCs. Implementing Sentry in an RSC-enabled framework like Next.js is as easy as running a single terminal command.

But what exactly is an RSC? Let’s pick one apart to see how it works under the hood.

The Anatomy of React Server Components

This new approach introduces two types of rendering components: Server Components and Client Components. The differences between these two are not how they function but where they execute and the environments they’re designed for. At the time of this writing, the only way to use RSCs is through React frameworks. And at the moment, there are only three frameworks that support them: Next.js, Gatsby, and RedwoodJS.

Server Components

Server Components are designed to be executed on the server, and their code is never shipped to the browser. The HTML output and any props they might be accepting are the only pieces that are served. This approach has multiple performance benefits and user experience enhancements:

Server Components allow for large dependencies to remain on the server side.
Imagine using a large library for a component. If you’re executing the component on the client side, it means that you’re also shipping the full library to the browser. With Server Components, you’re only taking the static HTML output and avoiding having to ship any JavaScript to the browser. Server Components are truly static, and they remove the whole hydration step.
Server Components are located much closer to the data sources — e.g., databases or file systems — they need to generate code.
They also leverage the server’s computational power to speed up compute-intensive rendering tasks and send only the generated results back to the client. They are also generated in a single pass, which avoids request waterfalls and HTTP round trips.
Server Components safely keep sensitive data and logic away from the browser.
That’s thanks to the fact that personal tokens and API keys are executed on a secure server rather than the client.
The rendering results can be cached and reused between subsequent requests and even across different sessions.
This significantly reduces rendering time, as well as the overall amount of data that is fetched for each request.

This architecture also makes use of HTML streaming, which means the server defers generating HTML for specific components and instead renders a fallback element in their place while it works on sending back the generated HTML. Streaming Server Components wrap components in <Suspense> tags that provide a fallback value. The implementing framework uses the fallback initially but streams the newly generated content when it‘s ready. We’ll talk more about streaming, but let’s first look at Client Components and compare them to Server Components.

Client Components

Client Components are the components we already know and love. They’re executed on the client side. Because of this, Client Components are capable of handling user interactions and have access to the browser APIs like localStorage and geolocation.

The term “Client Component” doesn’t describe anything new; they merely are given the label to help distinguish the “old” CSR components from Server Components. Client Components are defined by a “use client” directive at the top of their files.

“use client”
export default function LikeButton() {
const likePost = () => {
// …
return (
<button onClick={likePost}>Like</button>

In Next.js, all components are Server Components by default. That’s why we need to explicitly define our Client Components with “use client”. There’s also a “use server” directive, but it’s used for Server Actions (which are RPC-like actions that invoked from the client, but executed on the server). You don’t use it to define your Server Components.

You might (rightfully) assume that Client Components are only rendered on the client, but Next.js renders Client Components on the server to generate the initial HTML. As a result, browsers can immediately start rendering them and then perform hydration later.

The Relationship Between Server Components and Client Components

Client Components can only explicitly import other Client Components. In other words, we’re unable to import a Server Component into a Client Component because of re-rendering issues. But we can have Server Components in a Client Component’s subtree — only passed through the children prop. Since Client Components live in the browser and they handle user interactions or define their own state, they get to re-render often. When a Client Component re-renders, so will its subtree. But if its subtree contains Server Components, how would they re-render? They don’t live on the client side. That’s why the React team put that limitation in place.

But hold on! We actually can import Server Components into Client Components. It’s just not a direct one-to-one relationship because the Server Component will be converted into a Client Component. If you’re using server APIs that you can’t use in the browser, you’ll get an error; if not — you’ll have a Server Component whose code gets “leaked” to the browser.

This is an incredibly important nuance to keep in mind as you work with RSCs.

The Rendering Lifecycle

Here’s the order of operations that Next.js takes to stream contents:

The app router matches the page’s URL to a Server Component, builds the component tree, and instructs the server-side React to render that Server Component and all of its children components.
During render, React generates an “RSC Payload”. The RSC Payload informs Next.js about the page and what to expect in return, as well as what to fall back to during a <Suspense>.
If React encounters a suspended component, it pauses rendering that subtree and uses the suspended component’s fallback value.
When React loops through the last static component, Next.js prepares the generated HTML and the RSC Payload before streaming it back to the client through one or multiple chunks.
The client-side React then uses the instructions it has for the RSC Payload and client-side components to render the UI. It also hydrates each Client Component as they load.
The server streams in the suspended Server Components as they become available as an RSC Payload. Children of Client Components are also hydrated at this time if the suspended component contains any.

We will look at the RSC rendering lifecycle from the browser’s perspective momentarily. For now, the following figure illustrates the outlined steps we covered.

We’ll see this operation flow from the browser’s perspective in just a bit.

RSC Payload

The RSC payload is a special data format that the server generates as it renders the component tree, and it includes the following:

The rendered HTML,
Placeholders where the Client Components should be rendered,
References to the Client Components’ JavaScript files,
Instructions on which JavaScript files it should invoke,
Any props passed from a Server Component to a Client Component.

There’s no reason to worry much about the RSC payload, but it’s worth understanding what exactly the RSC payload contains. Let’s examine an example (truncated for brevity) from a demo app I created:

7:[“$”,”main”,null,{“className”:”page_main__GlU4n”,”children”:[[“$”,”$Lf”,null,{}],[“$”,”$8″,null,{“fallback”:[“$”,”p”,null,{“children”:”🌀 loading products…”}],”children”:”$L10″}]]}]
c:[[“$”,”meta”,”0″,{“name”:”viewport”,”content”:”width=device-width, initial-scale=1″}]…
9:[“$”,”p”,null,{“children”:[“🛍️ “,3]}]
10:[“$”,”ul”,null,{“children”:[[“$”,”li”,”1″,{“children”:[“Gloves”,” – $”,20,[“$…

To find this code in the demo app, open your browser’s developer tools at the Elements tab and look at the <script> tags at the bottom of the page. They’ll contain lines like:


Every line from the snippet above is an individual RSC payload. You can see that each line starts with a number or a letter, followed by a colon, and then an array that’s sometimes prefixed with letters. We won’t get into too deep in detail as to what they mean, but in general:

HL payloads are called “hints” and link to specific resources like CSS and fonts.
I payloads are called “modules,” and they invoke specific scripts. This is how Client Components are being loaded as well. If the Client Component is part of the main bundle, it’ll execute. If it’s not (meaning it’s lazy-loaded), a fetcher script is added to the main bundle that fetches the component’s CSS and JavaScript files when it needs to be rendered. There’s going to be an I payload sent from the server that invokes the fetcher script when needed.
“$” payloads are DOM definitions generated for a certain Server Component. They are usually accompanied by actual static HTML streamed from the server. That’s what happens when a suspended component becomes ready to be rendered: the server generates its static HTML and RSC Payload and then streams both to the browser.


Streaming allows us to progressively render the UI from the server. With RSCs, each component is capable of fetching its own data. Some components are fully static and ready to be sent immediately to the client, while others require more work before loading. Based on this, Next.js splits that work into multiple chunks and streams them to the browser as they become ready. So, when a user visits a page, the server invokes all Server Components, generates the initial HTML for the page (i.e., the page shell), replaces the “suspended” components’ contents with their fallbacks, and streams all of that through one or multiple chunks back to the client.

The server returns a Transfer-Encoding: chunked header that lets the browser know to expect streaming HTML. This prepares the browser for receiving multiple chunks of the document, rendering them as it receives them. We can actually see the header when opening Developer Tools at the Network tab. Trigger a refresh and click on the document request.

We can also debug the way Next.js sends the chunks in a terminal with the curl command:

curl -D – –raw localhost:3000 > chunked-response.txt

You probably see the pattern. For each chunk, the server responds with the chunk’s size before sending the chunk’s contents. Looking at the output, we can see that the server streamed the entire page in 16 different chunks. At the end, the server sends back a zero-sized chunk, indicating the end of the stream.

The first chunk starts with the <!DOCTYPE html> declaration. The second-to-last chunk, meanwhile, contains the closing </body> and </html> tags. So, we can see that the server streams the entire document from top to bottom, then pauses to wait for the suspended components, and finally, at the end, closes the body and HTML before it stops streaming.

Even though the server hasn’t completely finished streaming the document, the browser’s fault tolerance features allow it to draw and invoke whatever it has at the moment without waiting for the closing </body> and </html> tags.

Suspending Components

We learned from the render lifecycle that when a page is visited, Next.js matches the RSC component for that page and asks React to render its subtree in HTML. When React stumbles upon a suspended component (i.e., async function component), it grabs its fallback value from the <Suspense> component (or the loading.js file if it’s a Next.js route), renders that instead, then continues loading the other components. Meanwhile, the RSC invokes the async component in the background, which is streamed later as it finishes loading.

At this point, Next.js has returned a full page of static HTML that includes either the components themselves (rendered in static HTML) or their fallback values (if they’re suspended). It takes the static HTML and RSC payload and streams them back to the browser through one or multiple chunks.

As the suspended components finish loading, React generates HTML recursively while looking for other nested <Suspense> boundaries, generates their RSC payloads and then lets Next.js stream the HTML and RSC Payload back to the browser as new chunks. When the browser receives the new chunks, it has the HTML and RSC payload it needs and is ready to replace the fallback element from the DOM with the newly-streamed HTML. And so on.

In Figures 7 and 8, notice how the fallback elements have a unique ID in the form of B:0, B:1, and so on, while the actual components have a similar ID in a similar form: S:0 and S:1, and so on.

Along with the first chunk that contains a suspended component’s HTML, the server also ships an $RC function (i.e., completeBoundary from React’s source code) that knows how to find the B:0 fallback element in the DOM and replace it with the S:0 template it received from the server. That’s the “replacer” function that lets us see the component contents when they arrive in the browser.

The entire page eventually finishes loading, chunk by chunk.

Lazy-Loading Components

If a suspended Server Component contains a lazy-loaded Client Component, Next.js will also send an RSC payload chunk containing instructions on how to fetch and load the lazy-loaded component’s code. This represents a significant performance improvement because the page load isn’t dragged out by JavaScript, which might not even be loaded during that session.

At the time I’m writing this, the dynamic method to lazy-load a Client Component in a Server Component in Next.js does not work as you might expect. To effectively lazy-load a Client Component, put it in a “wrapper” Client Component that uses the dynamic method itself to lazy-load the actual Client Component. The wrapper will be turned into a script that fetches and loads the Client Component’s JavaScript and CSS files at the time they’re needed.


I know that’s a lot of plates spinning and pieces moving around at various times. What it boils down to, however, is that a page visit triggers Next.js to render as much HTML as it can, using the fallback values for any suspended components, and then sends that to the browser. Meanwhile, Next.js triggers the suspended async components and gets them formatted in HTML and contained in RSC Payloads that are streamed to the browser, one by one, along with an $RC script that knows how to swap things out.

The Page Load Timeline

By now, we should have a solid understanding of how RSCs work, how Next.js handles their rendering, and how all the pieces fit together. In this section, we’ll zoom in on what exactly happens when we visit an RSC page in the browser.

The Initial Load

As we mentioned in the TL;DR section above, when visiting a page, Next.js will render the initial HTML minus the suspended component and stream it to the browser as part of the first streaming chunks.

To see everything that happens during the page load, we’ll visit the “Performance” tab in Chrome DevTools and click on the “reload” button to reload the page and capture a profile. Here’s what that looks like:

When we zoom in at the very beginning, we can see the first “Parse HTML” span. That’s the server streaming the first chunks of the document to the browser. The browser has just received the initial HTML, which contains the page shell and a few links to resources like fonts, CSS files, and JavaScript. The browser starts to invoke the scripts.

After some time, we start to see the page’s first frames appear, along with the initial JavaScript scripts being loaded and hydration taking place. If you look at the frame closely, you’ll see that the whole page shell is rendered, and “loading” components are used in the place where there are suspended Server Components. You might notice that this takes place around 800ms, while the browser started to get the first HTML at 100ms. During those 700ms, the browser is continuously receiving chunks from the server.

Bear in mind that this is a Next.js demo app running locally in development mode, so it’s going to be slower than when it’s running in production mode.

The Suspended Component

Fast forward few seconds and we see another “Parse HTML” span in the page load timeline, but this one it indicates that a suspended Server Component finished loading and is being streamed to the browser.

We can also see that a lazy-loaded Client Component is discovered at the same time, and it contains CSS and JavaScript files that need to be fetched. These files weren’t part of the initial bundle because the component isn’t needed until later on; the code is split into their own files.

This way of code-splitting certainly improves the performance of the initial page load. It also makes sure that the Client Component’s code is shipped only if it’s needed. If the Server Component (which acts as the Client Component’s parent component) throws an error, then the Client Component does not load. It doesn’t make sense to load all of its code before we know whether it will load or not.

Figure 12 shows the DOMContentLoaded event is reported at the end of the page load timeline. And, just before that, we can see that the localhost HTTP request comes to an end. That means the server has likely sent the last zero-sized chunk, indicating to the client that the data is fully transferred and that the streaming communication can be closed.

The End Result

The main localhost HTTP request took around five seconds, but thanks to streaming, we began seeing page contents load much earlier than that. If this was a traditional SSR setup, we would likely be staring at a blank screen for those five seconds before anything arrives. On the other hand, if this was a traditional CSR setup, we would likely have shipped a lot more of JavaScript and put a heavy burden on both the browser and network.

This way, however, the app was fully interactive in those five seconds. We were able to navigate between pages and interact with Client Components that have loaded as part of the initial main bundle. This is a pure win from a user experience standpoint.


RSCs mark a significant evolution in the React ecosystem. They leverage the strengths of server-side and client-side rendering while embracing HTML streaming to speed up content delivery. This approach not only addresses the SEO and loading time issues we experience with CSR but also improves SSR by reducing server load, thus enhancing performance.

I’ve refactored the same RSC app I shared earlier so that it uses the Next.js Page router with SSR. The improvements in RSCs are significant:

Looking at these two reports I pulled from Sentry, we can see that streaming allows the page to start loading its resources before the actual request finishes. This significantly improves the Web Vitals metrics, which we see when comparing the two reports.

The conclusion: Users enjoy faster, more reactive interfaces with an architecture that relies on RSCs.

The RSC architecture introduces two new component types: Server Components and Client Components. This division helps React and the frameworks that rely on it — like Next.js — streamline content delivery while maintaining interactivity.

However, this setup also introduces new challenges in areas like state management, authentication, and component architecture. Exploring those challenges is a great topic for another blog post!

Despite these challenges, the benefits of RSCs present a compelling case for their adoption. We definitely will see guides published on how to address RSC’s challenges as they mature, but, in my opinion, they already look like the future of rendering practices in modern web development.

Choosing Between “What You Do Best” vs. “What You Like Best”

Original Source: https://www.hongkiat.com/blog/job-proficiency-vs-passion/

Occupation, profession or what we call nowadays “a job”, is one of the most important things in a person’s life.

When people started settling in cities and villages, a person’s job defined his status in the society. Surnames like Miller, Smith and Schneider were derived from occupations i.e. Miller (people who worked in mills), Smith (iron workers) and Schneider (dressmaker or tailor). Even today, the influence of job in our life sustains its behemoth significance.

In the professional world there might be some people who are good at their jobs and are fully satisfied with what they do. However, most job holders these days are discontent with some elements of their job.

Proficiency vs. Passion

Here’s an example: a friend of mine suffers from a unique case of job discontentment.

Although she is quite proficient in her work as an iOS developer and is being handsomely remunerated for it, her heart is stuck in pursuing a career in art and graphic design. If she were to leave that well-established career, many would deem her action as utter foolishness.

Still there are some who might tell her to “follow her heart”. Hence this article is a kind of “thinking out loud’ post for those who find themselves in the dilemma of choosing a job they are good at versus a job that they actually want to do.

Going with a Job You Are Good At
1. Skill Level

Pros – Being good at a job is synonymous with having a higher skill level in it.

Being the master of the art makes you an important part of the whole mechanics of your organization. Based on your skills, you are able to take up new challenges, work out solutions, and produce profitable results, all of which make your superiors nothing but happy.

Cons – From hardcore skills like engineering and designing to more embedded skills like business development and public relations, every craft has a saturation point.

No matter how proficient you are at doing something, there comes a time when you simply grow out of it. After reaching this level, you just keep reproducing work on already existing skill templates with very little room for learning anything further.

2. Financial Gains

Pros – Who doesn’t like money? When you are good at something and find the right place to put it to use, money comes running after you like crazy.

The story becomes especially interesting when you get paid for something you could easily do in your sleep, i.e., based on your skills you do not have to work too hard to reach your goal.

financial gainsfinancial gains

Cons – In almost every career there is a limit on the amount of income you can earn on each level. There are certain careers in which, no matter how high your expertise is, there is not much chance of increased financial gains once you reach the maximum income threshold.

Of course, you can take up after-office freelance work, but it will only leave you exhausted. Moreover, no matter how good you are in your body of work, being paid well for it depends a lot on your luck, apart from your talents. For everyone who is making a good living doing something they are good at, there are countless other equally talented people who are not able to do so just because they didn’t get a good chance to.

3. Career Longevity

Pros – Being adept in a specific field can certainly vouch for the longevity of your career in it.

The better you are in a certain job, the longer you will stay in it, and the longer you stay in a certain career, the greater will your credibility and reputation be. Furthermore, if you are good in your job and you make your superiors realize it, your vulnerability towards a layoff consequently decreases.

Cons – When you are proficient in a job, you tend to stay in it for a long time.

But career longevity can sometimes cause monotony and boredom, especially when it spreads over decades in a row. After all, the days of retiring from a company that you joined fresh out of college are long gone.

Going with a Job You Want to Do
1. Professional Gratification

Pros – There is no match for professional gratification, and what better way to achieve it than doing what you really want to do. Your interest in a job directly spells your devotion and dedication towards it.

professional gratificationprofessional gratification

Even if you have to compromise a bit over certain other factors, the mere feeling of satisfaction makes up for most of the missing elements. However, in a scenario when you are not able to do the job of your passion, you may keep coming to the office each day, but gradually your energy keeps dropping and your frustration level keeps on rising.

Cons – Professional gratification is a key factor in the success of your career; however, when you are responsible for the upbringing of your family or any other obligations, then moving to a whole new career just because you seek self-contentment could leave you nothing but heartbroken as well as financially broke.

Another downside can be that sometimes being too passionate about work can negatively impact your work-life balance, affecting your health, personal life, and family.

2. Refreshing New Start

Pros – Regardless of how excelled you have become in your job, when you go for the career of your dreams, the new start be like a fresh breeze in your professional life. The new start can revitalize your enthusiasm and can give you fresh-out-of-college energy towards work.

Cons – A job is no joke. Right from the beginning of your life in the professional field, one focuses all his or her energy on getting settled in the field and getting to the top of their game.

If the new start pushes you from the corner office, which you have earned with your dedication and hard work, to a newbie’s cubicle, then the decision of pursuing a new career should be properly calculated before you take the next step.

3. Increased Motivation

Pros – Working in your favorite field makes you more motivated towards your job.

No matter how late you start in a field, the sheer joy of handling certain tasks and the desire to complete tasks with passion, quickly takes you to the next level. This factor plays a key role in getting you to the top of the ladder in a job that you are fond of and consequently shows more motivation in it.


Cons – To get motivated is easy, but staying motivated is where the problem starts. One can easily say catchy phrases like, “fulfil your dreams” and “be your own master”, but to actually commit yourself to doing something every day might be more arduous than you think.

When you take what you love to do and make it into something you depend upon for survival for yourself and your family, the motivation can disappear quickly. Not to forget, turning your passion into a profession means you have clients, bosses, deadlines, and obligations, which automatically takes all the fun out of it.


Some people have a lifelong dream of doing something or having a certain career. However, the unforgiving waves of circumstances can make you make decisions that you might not deem as the right one.

So, is it alright to continue down the path life has taken you, especially when you have so well-established yourself in it, or should you go back and try to have a second go at your childhood dreams? The answer to this question highly depends on your own priorities.

My iOS developer friend has decided to continue her career in development while developing her graphic design interest by learning front-end interface design for iOS apps. The idea is to facilitate a smooth transition into a new career. Maybe, with a little strategy and calculation (and of course, some luck), you too can manage to achieve a bit of both, instead of all of each.

The post Choosing Between “What You Do Best” vs. “What You Like Best” appeared first on Hongkiat.