D30,31 Nanhey Park, Uttam Nagar, New Delhi- 110059, India

Things Web Developers Should Stop Doing

Things Web Developers Should Stop Doing
Developer Guide · 2025 Edition

Things Web Developers Should Stop Doing

We've all inherited bad habits — some from tutorials, some from Stack Overflow answers written in 2013, some from our own tired brains at 2 AM. This is a no-nonsense list of practices the web development community needs to collectively retire. No judgment. Just hard truths.



01
Code Smell

Using console.log() as Your Debugger

Scattering console.log("here") and console.log(data) across your codebase isn't debugging — it's guessing with extra steps. Your browser has a full-featured debugger with breakpoints, watch expressions, call stacks, and step-through execution. Use it.

Shipping console.log statements to production leaks implementation details and pollutes the user's DevTools. Set up an ESLint rule to catch them before they ever reach a PR.

console.log("user:", user)
console.log("reached here")
console.log(JSON.stringify(res))
Use breakpoints in DevTools
Use debugger; keyword intentionally
Strip logs via ESLint / build step
02
Security Risk

Storing Sensitive Data in localStorage

LocalStorage is not a vault. It's a plain-text key-value store accessible to any JavaScript running on your page — including third-party scripts, browser extensions, and XSS payloads. Storing JWTs, tokens, or user PII here is an open invitation.

For authentication tokens, prefer HttpOnly cookies. They can't be accessed by JavaScript at all, making XSS attacks far less damaging.

localStorage.setItem('authToken', jwt)
localStorage.setItem('userId', id)
Use HttpOnly + Secure cookies
Keep sensitive state server-side
03
Performance

Ignoring Accessibility Until Launch Day

Accessibility retrofitted is accessibility half-done. Semantic HTML, ARIA roles, focus management, and keyboard navigation are not an afterthought — they're architectural decisions. Bolting them on post-launch costs 10× more than building them in from the start.

The WCAG 2.2 guidelines aren't just about screen readers. They improve usability for everyone: keyboard users, people on slow connections, users with temporary impairments. Run Lighthouse and axe DevTools on every PR.

04
Anti-Pattern

Reaching for a Framework for Everything

Not every project needs React. Not every interaction needs a state management library. The instinct to npx create-react-app a landing page with three static sections and a contact form is costing your users 200 KB of JavaScript they didn't ask for.

Vanilla JS, HTML, and CSS have evolved dramatically. Before pulling in a dependency, ask: "Can the platform handle this natively?" More often than you think, the answer is yes.

"The best framework is no framework — until the complexity demands one."
05
Code Smell

Writing Inline Styles in JSX (At Scale)

Inline styles are fine for quick prototypes. In production codebases they become unmaintainable: no theming, no media queries, no pseudo-selectors, no deduplication. They bypass the cascade entirely and make design consistency nearly impossible.

Adopt a consistent styling strategy — CSS Modules, Tailwind, styled-components, or plain CSS with BEM. Whatever you choose, be consistent across the codebase.

// Stop this
<div style={{ fontSize: '14px', color: '#333', marginTop: '8px' }}>

// Do this
<div className={styles.caption}>
06
Performance

Skipping Image Optimization Entirely

Serving a 4 MB PNG where a 120 KB WebP would do is one of the most common and most damaging performance mistakes on the web. Images are typically the largest contributors to page weight and Largest Contentful Paint (LCP).

Use modern formats (WebP, AVIF), appropriate dimensions, lazy loading for below-the-fold images, and srcset for responsive images. Next.js's <Image> component and tools like Squoosh or Sharp make this trivial — there's no excuse.

<img src="hero.png" />
(4.2 MB, wrong size, no lazy load)
<img src="hero.avif" loading="lazy"
width="800" height="450"
srcset="hero-400.avif 400w, ..." />
07
Security Risk

Trusting Client-Side Validation Alone

Client-side validation is UX. Server-side validation is security. A user with DevTools open (or curl) can bypass every form validation you've written in React in under 30 seconds.

Always validate, sanitize, and authenticate on the server. The frontend validation is a courtesy layer. The backend is the law.

08
Maintainability

Committing Without Meaningful Messages

Your git history is documentation. "fix", "wip", "asdf", and "updates" are not commit messages — they're noise that makes debugging, reverting, and onboarding painful for everyone, including future you.

Follow Conventional Commits or at minimum write a message that answers: what changed and why? A well-maintained git log is worth more than most inline comments.

fix
wip
stuff
final final FINAL
fix(auth): redirect to /login on 401
feat(cart): persist items to localStorage
refactor(api): extract fetchUser helper
09
Performance

Abusing useEffect for Everything in React

The useEffect hook is not a generic lifecycle method. Reaching for it to sync state, derive computed values, or respond to user events is a sign that something has gone wrong in your mental model of React.

If you're computing a value from props or state — just compute it during render. If you're handling a user event — do it in the event handler. useEffect is for synchronizing with external systems: the DOM, browser APIs, subscriptions, timers.

// Stop — unnecessary effect
useEffect(() => {
  setFullName(first + ' ' + last);
}, [first, last]);

// Do — derive during render
const fullName = first + ' ' + last;
10
Anti-Pattern

Shipping Without Error Boundaries or Fallbacks

A single unhandled JavaScript error in a React tree can take down your entire UI — leaving users staring at a blank white page with zero context. This is unacceptable in production.

Implement React Error Boundaries around critical sections of your app. Add global window.onerror and unhandledrejection listeners. Integrate an error monitoring tool (Sentry, Datadog) so you hear about crashes before your users do.

Every async function should have a catch. Every data fetch should handle loading and error states. Assume things will fail — because they will.

Good developers write code that works.
Great developers write code that fails gracefully.

Leave A Comment

Your email address will not be published. Required fields are marked *

For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

Start chat
1