When I started my journey as a frontend engineer, I believed becoming better at my craft meant learning more frameworks, writing cleaner code, and building interfaces faster.

If I could take a Figma design, turn it into a responsive interface, integrate the APIs, and get everything working as expected, I considered that a job well done.

And to be fair, it was.

But over six years of building production applications across different industries, particularly fintech and edtech, I've come to understand that there's much more to frontend engineering than writing code that works.

I've worked on applications that started small and became increasingly complex. I've dealt with difficult bugs, changing product requirements, technical decisions that didn't age well, and features that required more thought than I initially expected.

Some lessons came from making mistakes. Others came from working with different teams, learning from more experienced engineers, and seeing how software behaves in production.

Looking back, there are a few things I wish I'd understood earlier.

Here are ten of them.

1. Understanding JavaScript Will Take You Further Than Chasing Frameworks

Early in my career, I was always interested in learning the next framework or library.

There was always something new to explore, and it sometimes felt like keeping up with the ecosystem was the only way to stay relevant.

But the more I worked with Vue, Nuxt, and other frontend technologies, the more I realised that a solid understanding of JavaScript was far more valuable than knowing the syntax of several frameworks.

Understanding closures, promises, asynchronous operations, the event loop, and how JavaScript handles objects and references has helped me solve problems that framework knowledge alone couldn't explain.

For example, knowing how asynchronous operations behave makes it easier to understand race conditions, unexpected state updates, and why a component might display outdated data.

Frameworks provide convenient ways to build applications, but the fundamentals explain what's happening underneath.

What I'd tell myself five years ago: Learn your framework, but invest just as much effort in understanding JavaScript and how the browser works.

2. Getting a Feature to Work Doesn't Mean It's Finished

Earlier in my career, I was mostly concerned with getting features to work.

If the API returned the expected response, the form submitted successfully, and the UI matched the design, I felt the task was complete.

Production experience changed that perspective.

Today, I find myself asking questions like:

  • What happens when the API fails?
  • What if the user submits the form twice?
  • What happens when the response is delayed?
  • What if the data is incomplete?
  • How easy will it be for another engineer to modify this feature?

These are the situations that often separate a feature that works during development from one that works reliably in production.

I've learned to think beyond the happy path and consider how the application should behave when things don't go as planned.

The lesson: A feature isn't truly complete simply because it works under ideal conditions. It should also handle unexpected situations gracefully.

3. Understanding the Product Makes You a Better Engineer

This is probably one of the biggest changes in how I approach my work.

When I was starting out, I focused heavily on implementation.

I'd receive a ticket, review the design, integrate the API, and move on to the next task.

Over time, I started paying more attention to the problem behind the ticket.

Why are we building this feature?

What problem does it solve?

How does it improve the user's experience?

And how does it contribute to the business?

Working on fintech products has made this particularly important.

For example, building a transfer flow isn't simply about collecting an amount, selecting a beneficiary, and calling an API.

You also need to think about how users understand transaction statuses, what happens when a transfer is delayed, and how the interface communicates errors without creating unnecessary confusion.

The technical implementation matters, but understanding the product helps you make better decisions about that implementation.

The lesson: Don't just focus on delivering features. Understand the problem you're solving and why it matters.

4. Simple Code Is Often Better Than Clever Code

There was a time when I thought writing sophisticated code was a sign of being a better engineer.

More abstractions, reusable utilities, design patterns, and layers of separation seemed like good architecture.

But working on larger applications has taught me that complexity comes with a cost.

I've encountered situations where a relatively simple feature became difficult to understand because the implementation had too many moving parts.

Sometimes, a straightforward function is all you need.

Sometimes, local component state is better than introducing another Pinia store.

And sometimes, having two focused components is more maintainable than creating one highly configurable component that tries to handle every possible use case.

This doesn't mean abstraction or reusability is bad.

It means we should introduce them when they solve a real problem.

The lesson: Good engineering isn't about how complicated your solution looks. It's about how clearly it solves the problem and how easy it is to maintain.

5. Debugging Is a Skill You Have to Develop Deliberately

I can remember times when my first response to a bug was to start changing code.

I'd try a different condition, move some logic around, add a console log, and hope the issue disappeared.

Sometimes it worked, but it wasn't an effective way to solve problems consistently.

Over the years, I've become more deliberate about debugging.

Before making changes, I try to understand what is happening.

What should the application be doing?

What is it actually doing?

Can I reproduce the issue?

Where does the behaviour begin to differ from what I expect?

Is the problem coming from the frontend, the API response, or an incorrect assumption?

This approach has been particularly useful when dealing with Vue reactivity, asynchronous operations, complex forms, and API integrations.

I've also learned to make better use of browser DevTools, Vue Devtools, network inspection, and automated tests.

The lesson: Understanding why something is broken is often more valuable than quickly finding a way to make the error disappear.

6. Performance Should Be Considered From the Beginning

Performance used to feel like something you worked on after completing a feature.

Build it first, then optimise it later.

While I still believe premature optimisation can create unnecessary complexity, I've learned that performance problems often come from decisions made much earlier.

Unnecessary API requests, large JavaScript bundles, poorly managed reactive state, and unoptimized assets can gradually affect the user experience.

In Vue and Nuxt applications, I've become more conscious of things like component rendering, lazy loading, API request patterns, and how data is fetched and shared across pages.

The goal isn't to optimise everything.

It's to understand the potential cost of technical decisions and measure performance where it matters.

The lesson: Performance isn't something you simply add at the end. It should influence how you design and build features.

7. Communication Is Just as Important as Technical Ability

One thing I've learned from working with different teams is that being technically good doesn't automatically make you effective.

You also need to communicate clearly.

That means knowing when to ask questions, explain technical decisions, raise concerns, and communicate blockers before they become bigger problems.

It also means being able to discuss technical trade-offs with product managers, designers, and other stakeholders who may not have the same technical background.

I've come to appreciate that good communication reduces misunderstandings and helps teams make better decisions.

And sometimes, asking the right question early can save hours of unnecessary implementation.

The lesson: Your ability to communicate your thinking is part of your value as an engineer.

8. Document Your Work and the Impact It Creates

This is something I genuinely wish I'd started doing much earlier.

As engineers, we often move from one task to another without taking time to reflect on what we've accomplished.

You build a dashboard, improve a user flow, fix a difficult bug, or introduce a reusable component.

Then you move on.

Months later, when you're updating your CV or preparing for an interview, you struggle to remember the details.

I've learned that it's important to document not just what you built, but why you built it and what changed as a result.

For example, instead of simply writing:

"Built a new onboarding flow."

It's more useful to explain the problem with the previous experience, the changes you introduced, and any improvements you were able to measure.

Not every contribution will have a percentage attached to it, and that's fine.

But being able to explain the reasoning and impact behind your work makes your experience much easier to communicate.

The lesson: Don't wait until you're applying for a job before trying to remember everything you've accomplished.

9. AI Can Make You Faster, but You Still Need to Think

AI-assisted development has become a significant part of modern software engineering.

Today, we can use AI tools to explore implementation approaches, generate tests, review code, understand unfamiliar systems, and speed up repetitive tasks.

I've found these tools useful, particularly when exploring unfamiliar technologies or working through complex problems.

But I've also learned that generating code quickly isn't the same as solving a problem correctly.

AI can suggest an implementation that looks reasonable but doesn't account for your application's architecture, business requirements, or edge cases.

That's why understanding what you're building remains important.

You still need to review the output, question assumptions, test the implementation, and take responsibility for what eventually reaches production.

I see AI as something that should improve my productivity and engineering judgment, not replace them.

The lesson: Use AI to work more effectively, but don't outsource your understanding of the problem.

10. Be Intentional About Your Career Growth

For a long time, I believed that if I continued improving technically and delivering good work, career growth would naturally follow.

I've since realised that becoming a better engineer and building a meaningful career require different kinds of effort.

Technical ability matters, but so does how you position yourself, the problems you choose to work on, and the relationships you build along the way.

You also need to think about what you want to be known for.

For me, that has meant becoming more intentional about sharing what I've learned from building production applications, writing technical articles, participating in developer communities, and developing a deeper understanding of software architecture.

It's also one of the reasons I started sharing my Vue Nuggets series.

I wanted to do more than simply consume knowledge. I wanted to document what I've learned, contribute to conversations within the developer community, and hopefully help someone avoid mistakes I've made.

I'm still learning how to do that consistently.

But I wish I'd started earlier.

The lesson: Don't leave your career growth entirely to chance. Be deliberate about the skills you develop, the work you do, and how you communicate your value.

Final Thoughts

Looking back over the past six years, I can confidently say that my understanding of frontend engineering has changed.

I still enjoy building interfaces, solving technical problems, and exploring new technologies.

But I now spend more time thinking about the bigger picture.

How does this feature affect the user?

Will this implementation be easy to maintain?

What happens when something goes wrong?

Are we solving the right problem?

And how can I make the work easier for the next engineer who touches this code?

I don't have all the answers, and I don't expect to.

There are still things I'm learning, decisions I would approach differently, and areas where I want to improve.

But if there's one thing these years have taught me, it's that growth in software engineering goes beyond becoming better at writing code.

It's about developing better judgment, understanding the impact of your work, and learning to approach problems with more clarity and intention.

If I could go back five years, I'd tell myself this:

Don't focus only on becoming an engineer who can build anything. Work towards becoming an engineer who understands what is worth building, why it matters, and how to build it well.

And if you've been in frontend engineering for a while, I'd love to know:

What's one thing you wish you'd understood earlier in your career?