Early in my frontend career, I wasn’t struggling because JavaScript was hard.
I struggled because I didn’t understand engineering thinking.
Here are the mistakes that slowed me down — and the exact technical shifts that finally pushed me forward.
1. Focusing on UI output instead of understanding the architecture
I used to write components quickly… and rewrite them even quicker when the project grew.
What I learned:
Frontend is architecture-heavy. Naming, data ownership, routing boundaries, API strategy, state placement — everything matters.
Fix in practice:
- Co-located state with the smallest responsible component
- Used “feature-first” folder structure
- Adopted clear boundaries between server state (React Query) and UI state (Zustand/Context)
- Removed cross-feature imports to avoid spaghetti
This alone made my codebases far more predictable.
2. Copy–pasting solutions without understanding internals
I solved problems fast, but only on the surface.
Whenever something broke, I couldn't debug deeper because I never knew how it actually worked.
Fix in practice:
- Studied the React reconciliation RFC
- Read how the browser event loop schedules microtasks vs macrotasks
- Explored how React Query caches and invalidates data
- Learned how Next.js handles RSC hydration boundaries
Reading internals gave me “X-ray vision” during debugging.
3. Treating performance as a final step instead of a design constraint
I used to optimise only when Lighthouse screamed at me.
Fix in practice:
- Measured hydration cost and moved heavy UI to server components
- Reduced bundle size using dynamic imports + route-level code splitting
- Cached expensive calculations using
useMemoonly where profiling proved it helped - Added proper caching headers + ISR for API-heavy pages
Performance improved because I designed with it in mind.
4. Over-engineering small features
I thought adding abstraction made me “senior”.
Fix in practice:
- Used reducers only for genuinely complex state transitions
- Avoided wrapper components when plain JSX worked
- Stopped making utility functions for one-line logic
- Followed the “start simple → scale when needed” rule
Removing unnecessary layers made my code easier to read and maintain.
5. Taking CSS lightly
My layouts looked fine… until they broke on a different screen size or when content changed.
Fix in practice:
- Learned CSS cascade layers (huge mental unlock)
- Used logical properties for RTL-friendly layouts
- Adopted consistent spacing/typography tokens
- Designed components with intrinsic sizing first, not pixel-perfect assumptions
CSS became less “trial and error” and more “predictable behaviour”.
6. Random learning with no system
I bounced between tutorials, and it felt like progress… except nothing stuck.
Fix in practice:
- Followed a clear roadmap
- Built real projects instead of cloning UIs
- Took notes with examples, not theory
- Revised older codebases to see improvement clearly
This structured approach finally created momentum.
7. Ignoring accessibility until a real project forced me to care
My mindset changed when I worked on a government project that had to meet WCAG.
Fix in practice:
- Ensured every interactive element was keyboard-first
- Used semantic markup before ARIA
- Tested with screen readers
- Checked contrast ratios and focus paths
- Avoided “div soup” that confuses assistive tech
Accessibility stopped being a checkbox; it became a performance and UX enhancer.
Why I Wrote This
Every engineer grows through mistakes — but some mistakes slow the journey more than others.
These were mine.
If you're somewhere in this list, you’re not behind — you’re right where most of us started.
Top comments (0)