<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Build for Search</title>
    <description>The latest articles on DEV Community by Build for Search (@buildforsearch).</description>
    <link>https://dev.to/buildforsearch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4179709%2F70cd3e87-690c-4cd3-9934-c5f787640c7d.png</url>
      <title>DEV Community: Build for Search</title>
      <link>https://dev.to/buildforsearch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/buildforsearch"/>
    <language>en</language>
    <item>
      <title>The Hidden Cost of Poor Code Structure in Custom Web Applications</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Sun, 01 Nov 2026 10:31:07 +0000</pubDate>
      <link>https://dev.to/buildforsearch/the-hidden-cost-of-poor-code-structure-in-custom-web-applications-i6l</link>
      <guid>https://dev.to/buildforsearch/the-hidden-cost-of-poor-code-structure-in-custom-web-applications-i6l</guid>
      <description>&lt;p&gt;A web application can work perfectly when it is first launched. Pages load, forms submit, users can log in, and everything seems to be running smoothly.&lt;/p&gt;

&lt;p&gt;But things often change when the application starts growing.&lt;/p&gt;

&lt;p&gt;A client requests a new feature. Suddenly, changing one component affects three other pages. A developer spends hours understanding code written months ago. Even fixing a simple bug becomes more difficult than it should be.&lt;/p&gt;

&lt;p&gt;This is something many developers eventually experience. Quite often, the problem isn't the programming language or framework. It's the way the application was structured from the beginning.&lt;/p&gt;

&lt;p&gt;If you're exploring &lt;strong&gt;&lt;a href="https://rankifydev.com/novafy" rel="noopener noreferrer"&gt;Custom Web Development Services&lt;/a&gt;&lt;/strong&gt;, one thing worth considering is how the application will be maintained after launch, not just how quickly it can be developed.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Everything Lives in One Place
&lt;/h2&gt;

&lt;p&gt;One common mistake in smaller applications is putting too much logic inside a single file or component.&lt;/p&gt;

&lt;p&gt;For example, a controller might handle database queries, validation, authentication, business rules, and response formatting all together.&lt;/p&gt;

&lt;p&gt;Initially, this approach feels convenient. There are fewer files to manage, and development seems faster.&lt;/p&gt;

&lt;p&gt;But imagine coming back to that same controller six months later. Adding a new condition might break an existing feature because different responsibilities are tightly connected.&lt;/p&gt;

&lt;p&gt;The application hasn't necessarily become badly written overnight. It has simply become harder to change.&lt;/p&gt;

&lt;p&gt;Separating responsibilities makes code easier to understand, test, and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Responsibilities Clear
&lt;/h2&gt;

&lt;p&gt;A maintainable application should have a reasonable separation between its different parts.&lt;/p&gt;

&lt;p&gt;For example, in a typical web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controllers handle incoming requests and responses.&lt;/li&gt;
&lt;li&gt;Services contain business logic.&lt;/li&gt;
&lt;li&gt;Models or repositories handle data access.&lt;/li&gt;
&lt;li&gt;Middleware handles shared request-level operations.&lt;/li&gt;
&lt;li&gt;Validation logic checks incoming data before processing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This doesn't mean every small function needs its own file or class. Overengineering can create just as much confusion as poorly organized code.&lt;/p&gt;

&lt;p&gt;The goal is to make it clear where a particular piece of functionality belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Make Components Responsible for Everything
&lt;/h2&gt;

&lt;p&gt;The same problem appears in frontend development.&lt;/p&gt;

&lt;p&gt;A React component might handle API requests, form validation, data formatting, state management, and rendering all at once.&lt;/p&gt;

&lt;p&gt;As the component grows, understanding its behaviour becomes harder.&lt;/p&gt;

&lt;p&gt;A better approach is to keep components focused on their purpose and move reusable logic into appropriate hooks or utility functions.&lt;/p&gt;

&lt;p&gt;React's official documentation on &lt;a href="https://react.dev/learn/choosing-the-state-structure" rel="noopener noreferrer"&gt;choosing the state structure&lt;/a&gt; is a useful resource for understanding how to organize application state without introducing unnecessary complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make Your Code Easier to Change
&lt;/h2&gt;

&lt;p&gt;Writing code is only part of the job. Someone will eventually need to read, debug, modify, and extend it.&lt;/p&gt;

&lt;p&gt;This is why naming matters. A function called &lt;code&gt;processData()&lt;/code&gt; doesn't explain much. A function called &lt;code&gt;calculateOrderTotal()&lt;/code&gt; gives the next developer a much clearer idea of its responsibility.&lt;/p&gt;

&lt;p&gt;The same applies to folder structures, API naming, configuration, and documentation.&lt;/p&gt;

&lt;p&gt;JavaScript applications can also benefit from a clear module structure. MDN's guide to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;JavaScript modules&lt;/a&gt; explains how code can be organized into separate, reusable modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Think About Maintenance Before It Becomes a Problem
&lt;/h2&gt;

&lt;p&gt;You don't need an enterprise-level architecture for every project.&lt;/p&gt;

&lt;p&gt;A small business website and a large SaaS platform have very different requirements. The architecture should match the actual complexity of the application.&lt;/p&gt;

&lt;p&gt;However, even a relatively small project benefits from clear naming, sensible separation of responsibilities, reusable code, and consistent development practices.&lt;/p&gt;

&lt;p&gt;The best code structure isn't necessarily the most complicated one.&lt;/p&gt;

&lt;p&gt;It's the one that allows another developer to understand the application without spending days figuring out where everything belongs.&lt;/p&gt;

&lt;p&gt;In the long run, that can save more development time than trying to write everything as quickly as possible on day one.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Is Web Development Becoming Too Complicated?</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Sat, 31 Oct 2026 15:05:38 +0000</pubDate>
      <link>https://dev.to/buildforsearch/is-web-development-becoming-too-complicated-2h7a</link>
      <guid>https://dev.to/buildforsearch/is-web-development-becoming-too-complicated-2h7a</guid>
      <description>&lt;p&gt;A few years ago, building a website felt much simpler. You could write HTML, CSS, and JavaScript, add some functionality, and get the job done.&lt;/p&gt;

&lt;p&gt;Today, we have dozens of frameworks, libraries, build tools, state management solutions, and development tools to choose from.&lt;/p&gt;

&lt;p&gt;These tools are useful, no doubt. But sometimes I feel we spend more time choosing and configuring tools than actually building the product.&lt;/p&gt;

&lt;p&gt;For a simple project, do we really need a complex architecture and multiple dependencies?&lt;/p&gt;

&lt;p&gt;I'm curious about what other developers think.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are modern tools making web development easier, or are we making simple projects unnecessarily complicated?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What is your approach when starting a new project? Do you prefer a simple setup or a more advanced technology stack?&lt;/p&gt;

&lt;p&gt;Share your experience. I'd love to hear different perspectives.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>development</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>Custom Web Development: 6 Decisions That Can Make or Break Your Next Project</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Fri, 30 Oct 2026 16:21:19 +0000</pubDate>
      <link>https://dev.to/buildforsearch/custom-web-development-6-decisions-that-can-make-or-break-your-next-project-2oie</link>
      <guid>https://dev.to/buildforsearch/custom-web-development-6-decisions-that-can-make-or-break-your-next-project-2oie</guid>
      <description>&lt;p&gt;Building a custom web application is exciting, especially when a business has requirements that ready-made platforms cannot handle easily.&lt;/p&gt;

&lt;p&gt;But custom development also introduces decisions that affect the entire project. Choosing the wrong architecture, adding unnecessary features, or ignoring maintenance requirements can make even a small application difficult to manage.&lt;/p&gt;

&lt;p&gt;Before writing the first component or creating the database, it is worth thinking through a few important areas.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand the Actual Business Problem
&lt;/h2&gt;

&lt;p&gt;Start by identifying what the application needs to solve.&lt;/p&gt;

&lt;p&gt;Does the business need customer accounts, payment processing, inventory management, appointment booking, or internal dashboards?&lt;/p&gt;

&lt;p&gt;Write down the main user journeys before selecting a technology stack. This helps separate essential features from ideas that can be introduced later.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Choose Technologies Based on Requirements
&lt;/h2&gt;

&lt;p&gt;Developers sometimes choose technologies because they are popular rather than because they fit the project.&lt;/p&gt;

&lt;p&gt;A content-focused website might work perfectly with a CMS. A complex application with custom permissions and workflows may need a dedicated backend and database.&lt;/p&gt;

&lt;p&gt;The best stack is the one your team can maintain while meeting the project's actual requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Keep the Architecture Understandable
&lt;/h2&gt;

&lt;p&gt;A small application does not automatically need microservices or complicated infrastructure.&lt;/p&gt;

&lt;p&gt;Start with clear modules, sensible separation of responsibilities, and well-defined API boundaries.&lt;/p&gt;

&lt;p&gt;As the application grows, you can introduce additional architectural complexity when there is a real reason to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Think About Security Early
&lt;/h2&gt;

&lt;p&gt;Security should not be added as a final development task.&lt;/p&gt;

&lt;p&gt;Validate sensitive operations on the server, protect API credentials, use appropriate authentication, and enforce authorization checks for different user roles.&lt;/p&gt;

&lt;p&gt;Never assume that hiding a button in the frontend is sufficient to protect an operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Test Performance With Real Measurements
&lt;/h2&gt;

&lt;p&gt;A website can feel fast during local development but behave differently in production.&lt;/p&gt;

&lt;p&gt;Large JavaScript bundles, inefficient database queries, oversized images, and unnecessary API calls can all affect performance.&lt;/p&gt;

&lt;p&gt;Measure actual bottlenecks before optimizing. Tools such as &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;Google PageSpeed Insights&lt;/a&gt; can help evaluate frontend performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Plan for Maintenance Before Launch
&lt;/h2&gt;

&lt;p&gt;A custom application will need updates, bug fixes, security patches, and new features.&lt;/p&gt;

&lt;p&gt;Use version control, document important integrations, maintain separate environments, and establish a reliable deployment process.&lt;/p&gt;

&lt;p&gt;These practices make future changes easier and reduce the risk of breaking existing functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Something That Can Grow With Its Users
&lt;/h2&gt;

&lt;p&gt;Good custom development is not about using the most complicated technology or building every possible feature.&lt;/p&gt;

&lt;p&gt;It is about understanding the problem, selecting appropriate tools, writing maintainable code, and making decisions that support future requirements.&lt;/p&gt;

&lt;p&gt;A well-planned application should solve today's problem without making tomorrow's improvements unnecessarily difficult.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article was prepared with AI assistance and reviewed for technical accuracy. The author is responsible for verifying its examples and guidance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Custom Web Development Services: 5 Technical Decisions to Make Before You Build</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Thu, 29 Oct 2026 16:34:51 +0000</pubDate>
      <link>https://dev.to/buildforsearch/custom-web-development-services-5-technical-decisions-to-make-before-you-build-44mj</link>
      <guid>https://dev.to/buildforsearch/custom-web-development-services-5-technical-decisions-to-make-before-you-build-44mj</guid>
      <description>&lt;p&gt;Choosing how to build a website is not just a design decision. It affects performance, maintainability, security, and how easily a business can introduce new features later.&lt;/p&gt;

&lt;p&gt;For a simple business website, a ready-made platform may be enough. But when a company needs custom workflows, third-party integrations, complex user roles, or functionality that existing themes cannot handle, custom development becomes worth considering.&lt;/p&gt;

&lt;p&gt;The important question is not whether custom development is always better. It is whether the additional flexibility solves a real problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start With Requirements, Not Frameworks
&lt;/h2&gt;

&lt;p&gt;Developers sometimes choose a framework before understanding what the application needs to do.&lt;/p&gt;

&lt;p&gt;A better starting point is to identify the main user journeys. Will customers create accounts? Does the application need payments, dashboards, booking systems, or connections to external APIs? Will administrators manage content or process orders?&lt;/p&gt;

&lt;p&gt;Write down the core requirements and separate essential features from those that can wait.&lt;/p&gt;

&lt;p&gt;This prevents the project from becoming unnecessarily complicated and helps the team estimate development time more realistically.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Choose an Architecture That Fits the Project
&lt;/h2&gt;

&lt;p&gt;A small company website usually does not need the same architecture as a multi-tenant SaaS application.&lt;/p&gt;

&lt;p&gt;For a content-focused website, a conventional CMS might offer everything the business needs. An application with complex business logic may benefit from a dedicated backend, a structured database, and a frontend that communicates through APIs.&lt;/p&gt;

&lt;p&gt;The right architecture should make the application easier to maintain, not simply make the technology stack look impressive.&lt;/p&gt;

&lt;p&gt;Before adding microservices, multiple databases, or complicated infrastructure, consider whether a simpler design would meet the requirements. Unnecessary complexity increases development and maintenance costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Treat Performance as a Feature
&lt;/h2&gt;

&lt;p&gt;Performance problems are often introduced through small decisions: loading large images, importing entire libraries for a single function, making unnecessary API requests, or rendering components that do not need to update.&lt;/p&gt;

&lt;p&gt;Measure performance early rather than waiting until launch.&lt;/p&gt;

&lt;p&gt;For frontend applications, review JavaScript bundle size, image optimization, caching, and rendering behavior. For backend systems, examine slow database queries, response times, and external API dependencies.&lt;/p&gt;

&lt;p&gt;Google's &lt;a href="https://web.dev/learn/performance" rel="noopener noreferrer"&gt;web.dev performance guides&lt;/a&gt; provide practical explanations of web performance techniques. Its &lt;a href="https://web.dev/articles/vitals" rel="noopener noreferrer"&gt;Core Web Vitals documentation&lt;/a&gt; also explains key user-experience measurements.&lt;/p&gt;

&lt;p&gt;The goal is not to optimize every line of code prematurely. It is to identify bottlenecks that affect real users.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Plan for Security and Maintenance
&lt;/h2&gt;

&lt;p&gt;A website is not finished when it goes live. Dependencies need updates, errors need investigation, and business requirements will change.&lt;/p&gt;

&lt;p&gt;Use server-side validation for sensitive operations instead of trusting frontend checks alone. Store credentials securely, apply appropriate access controls, and avoid exposing private API keys in client-side code.&lt;/p&gt;

&lt;p&gt;Document important integrations and keep development, testing, and production environments separate. These practices make it easier to investigate problems and introduce changes without breaking existing functionality.&lt;/p&gt;

&lt;p&gt;Security and maintainability should be part of the original development plan, not tasks postponed until something goes wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make SEO and Accessibility Part of the Build
&lt;/h2&gt;

&lt;p&gt;Technical quality also includes how people and search engines interact with the website.&lt;/p&gt;

&lt;p&gt;Use descriptive URLs, semantic HTML, accessible navigation, meaningful page titles, and crawlable links. If the project uses JavaScript rendering, verify that important page content can be discovered and indexed.&lt;/p&gt;

&lt;p&gt;Google's &lt;a href="https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics" rel="noopener noreferrer"&gt;JavaScript SEO documentation&lt;/a&gt; explains common considerations for JavaScript-based websites.&lt;/p&gt;

&lt;p&gt;Accessibility deserves the same attention. Keyboard navigation, readable contrast, descriptive form labels, and useful error messages improve the experience for a wider range of users.&lt;/p&gt;

&lt;p&gt;These details are easier to incorporate during development than to retrofit across a large application later.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Does Custom Development Make Sense?
&lt;/h2&gt;

&lt;p&gt;Custom development is useful when a business has requirements that cannot be handled efficiently by an existing platform, or when its workflows justify the extra flexibility.&lt;/p&gt;

&lt;p&gt;Before committing to a project, compare the total cost of development, hosting, maintenance, future changes, and integrations. Sometimes a CMS or established framework is the more practical choice. In other cases, a tailored application can provide a better long-term fit.&lt;/p&gt;

&lt;p&gt;If you are evaluating a project that needs a tailored solution, &lt;a href="https://rankifydev.com/novafy" rel="noopener noreferrer"&gt;Custom Web Development Services&lt;/a&gt; is a relevant place to explore the custom development approach.&lt;/p&gt;

&lt;p&gt;The best technical decision is the one that solves the actual business problem while keeping the application understandable, secure, and manageable as it grows.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to Design a Database Schema That Won't Become a Problem Later</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Wed, 28 Oct 2026 16:16:43 +0000</pubDate>
      <link>https://dev.to/buildforsearch/how-to-design-a-database-schema-that-wont-become-a-problem-later-14pn</link>
      <guid>https://dev.to/buildforsearch/how-to-design-a-database-schema-that-wont-become-a-problem-later-14pn</guid>
      <description>&lt;p&gt;A database schema can look perfectly fine when an application has only a few users and a handful of records. The problems often appear months later, when new features are added, relationships become more complicated, and developers start struggling to change existing tables without breaking something else.&lt;/p&gt;

&lt;p&gt;Good database design is not about predicting every future requirement. It is about making today's data structure clear enough to support reasonable changes tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start With Relationships, Not Tables
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application. You need to store customers, products, orders, and order items.&lt;/p&gt;

&lt;p&gt;A beginner might create one large table containing the customer's name, product name, price, order date, and quantity in every row.&lt;/p&gt;

&lt;p&gt;This appears convenient initially, but it creates duplication. A customer placing ten orders may have their information repeated across multiple rows. Updating that information becomes unnecessarily complicated.&lt;/p&gt;

&lt;p&gt;A more maintainable approach separates entities according to their responsibilities.&lt;/p&gt;

&lt;p&gt;Customers belong in a customers table. Products belong in a products table. Each order belongs in an orders table, while individual products purchased in an order belong in an order_items table.&lt;/p&gt;

&lt;p&gt;The relationships between these tables allow the application to represent real business rules without repeating the same information everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical SQL Example
&lt;/h2&gt;

&lt;p&gt;Consider this simplified PostgreSQL schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
        &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
        &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;order_items&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;unit_price&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
        &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unit_price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example establishes several important rules. Customer emails must be unique, products cannot have negative prices, and an order item cannot reference a nonexistent product or order.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;unit_price&lt;/code&gt; column also deserves attention. It records the price associated with the item when the order is created. If the product's current price changes later, the historical order can still retain its original price.&lt;/p&gt;

&lt;p&gt;For more details about these database features, see the official &lt;a href="https://www.postgresql.org/docs/current/ddl-constraints.html" rel="noopener noreferrer"&gt;PostgreSQL documentation on constraints&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Rely on the Frontend to Protect Your Data
&lt;/h2&gt;

&lt;p&gt;Frontend validation is useful for giving users immediate feedback, but it should not be the only layer enforcing important business rules.&lt;/p&gt;

&lt;p&gt;For example, a form might prevent a customer from submitting a quantity of zero. However, someone could bypass that form and send a request directly to the backend.&lt;/p&gt;

&lt;p&gt;The database constraint provides another layer of protection by rejecting invalid data even when an application request contains a mistake.&lt;/p&gt;

&lt;p&gt;Not every rule belongs in a database constraint. Complex business workflows may need validation in the application service as well. The goal is to enforce essential data integrity rules at the appropriate layers rather than assuming every request will be valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Think About Queries Before Adding Indexes
&lt;/h2&gt;

&lt;p&gt;As the application grows, developers often add indexes whenever a query becomes slow. Indexes can help, but adding them without understanding the workload can increase storage requirements and slow down writes.&lt;/p&gt;

&lt;p&gt;Start by identifying the queries the application actually runs.&lt;/p&gt;

&lt;p&gt;If customers frequently retrieve their orders using &lt;code&gt;customer_id&lt;/code&gt;, an index on that column may help. PostgreSQL automatically indexes primary keys and unique constraints, but it does not automatically create an index on every referencing foreign-key column.&lt;/p&gt;

&lt;p&gt;You might add an index like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_orders_customer_id&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whether this index is useful depends on the query patterns, table size, and existing indexes. Use &lt;code&gt;EXPLAIN&lt;/code&gt; to inspect how PostgreSQL plans to execute a query, and test with representative data before making performance decisions.&lt;/p&gt;

&lt;p&gt;The official &lt;a href="https://www.postgresql.org/docs/current/indexes.html" rel="noopener noreferrer"&gt;PostgreSQL documentation on indexes&lt;/a&gt; explains the available index types and their trade-offs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid Designing for Imaginary Requirements
&lt;/h2&gt;

&lt;p&gt;Future flexibility is valuable, but excessive abstraction can make a database harder to understand.&lt;/p&gt;

&lt;p&gt;Creating dozens of tables for features that may never exist adds complexity without necessarily improving maintainability. Storing every possible attribute in a generic key-value structure can also make ordinary queries more difficult.&lt;/p&gt;

&lt;p&gt;Start with known business requirements. Separate data where relationships and responsibilities justify it, enforce important constraints, and review the design when actual requirements change.&lt;/p&gt;

&lt;p&gt;A schema should evolve with the application, not attempt to predict every possible future feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review the Schema Before the Application Grows
&lt;/h2&gt;

&lt;p&gt;A useful database review asks a few practical questions.&lt;/p&gt;

&lt;p&gt;Can the same information be updated consistently? Are relationships enforced? Can the application represent historical transactions correctly? Do important queries have suitable indexes? Can a developer understand the purpose of each table without guessing?&lt;/p&gt;

&lt;p&gt;These questions are relevant to web applications where reliable content management, publishing workflows, and structured website data matter.&lt;/p&gt;

&lt;p&gt;For developers exploring &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;, RankifyDev offers website development and SEO-related services. Technical architecture, maintainable code, and a well-organized website all contribute to building a reliable online presence.&lt;/p&gt;

&lt;p&gt;A well-designed database will not automatically make an application scalable, but it gives developers a clearer foundation to build on.&lt;/p&gt;

&lt;p&gt;The best time to think about database structure is before duplicated data and fragile relationships become difficult to remove. A small amount of planning early on can make future features much easier to implement and maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; This article was prepared with AI assistance. Review the SQL examples and test them in your intended PostgreSQL environment before using them in production.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>postgres</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Developers Should Stop Putting Business Logic Inside Controllers</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Sun, 25 Oct 2026 14:07:22 +0000</pubDate>
      <link>https://dev.to/buildforsearch/why-developers-should-stop-putting-business-logic-inside-controllers-77n</link>
      <guid>https://dev.to/buildforsearch/why-developers-should-stop-putting-business-logic-inside-controllers-77n</guid>
      <description>&lt;p&gt;A controller often starts small. It receives a request, checks a few values, calls a database method, and returns a response.&lt;/p&gt;

&lt;p&gt;Then the application grows.&lt;/p&gt;

&lt;p&gt;A new condition appears. Another permission check gets added. Email notifications become part of the request. Soon, a single controller method handles validation, business rules, database operations, and error handling.&lt;/p&gt;

&lt;p&gt;The code still works, but changing one feature becomes harder than it should be.&lt;/p&gt;

&lt;p&gt;This is where separating business logic from controllers makes a real difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Fat Controllers
&lt;/h2&gt;

&lt;p&gt;Consider a simple order creation endpoint in a PHP or Node.js application.&lt;/p&gt;

&lt;p&gt;The controller receives the cart, checks the user's account, calculates the total, applies a discount, verifies stock, creates the order, reduces inventory, and sends a confirmation email.&lt;/p&gt;

&lt;p&gt;At first, putting everything in one method might seem convenient. There are fewer files to manage, and the complete process is visible in one place.&lt;/p&gt;

&lt;p&gt;The difficulty appears when the same rules are needed elsewhere.&lt;/p&gt;

&lt;p&gt;A mobile application might create orders through a different endpoint. An administrator might create an order manually. A scheduled task might process pending purchases.&lt;/p&gt;

&lt;p&gt;If each entry point contains its own version of the order logic, the application can develop inconsistent behavior. One path may validate stock correctly while another forgets a check.&lt;/p&gt;

&lt;p&gt;The problem is not the number of lines in a controller. It is the number of responsibilities the controller owns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give Each Layer a Clear Responsibility
&lt;/h2&gt;

&lt;p&gt;A controller should primarily coordinate the HTTP request.&lt;/p&gt;

&lt;p&gt;It can validate request structure, identify the authenticated user, call the appropriate application service, and translate the result into an HTTP response.&lt;/p&gt;

&lt;p&gt;A service or use-case layer can handle the actual business operation. It decides whether the order can be placed, applies relevant business rules, and coordinates the necessary operations.&lt;/p&gt;

&lt;p&gt;Repositories or data-access components can handle persistence when that abstraction is useful for the application.&lt;/p&gt;

&lt;p&gt;These layers do not need to become an elaborate framework. Their purpose is to make responsibilities clear.&lt;/p&gt;

&lt;p&gt;For example, an order controller might call a method such as &lt;code&gt;placeOrder(userId, cartItems)&lt;/code&gt;. The service then handles the order workflow, while the controller focuses on returning an appropriate response.&lt;/p&gt;

&lt;p&gt;The method name describes the business action instead of exposing every implementation detail.&lt;/p&gt;

&lt;p&gt;For background on structuring application responsibilities, see Martin Fowler's &lt;a href="https://martinfowler.com/eaaCatalog/serviceLayer.html" rel="noopener noreferrer"&gt;Service Layer pattern&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Rules Should Be Testable Without HTTP
&lt;/h2&gt;

&lt;p&gt;Imagine a rule that prevents an order when a product has insufficient stock.&lt;/p&gt;

&lt;p&gt;If the rule lives inside a controller, testing it may require creating an HTTP request, setting up authentication, and checking the response.&lt;/p&gt;

&lt;p&gt;If the rule is handled by a dedicated service, you can test the decision more directly by providing products, quantities, and available stock.&lt;/p&gt;

&lt;p&gt;This makes it easier to test scenarios such as insufficient inventory, invalid discounts, unavailable products, and successful orders.&lt;/p&gt;

&lt;p&gt;You can still write integration tests for the complete HTTP flow. The advantage is that business rules no longer depend entirely on the web layer to be tested.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://martinfowler.com/eaaCatalog/domainModel.html" rel="noopener noreferrer"&gt;Martin Fowler article on Domain Model&lt;/a&gt; explains an approach for organizing business logic around the concepts and rules of a domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid Turning Every Service Into a Giant Class
&lt;/h2&gt;

&lt;p&gt;Separating business logic does not mean moving an entire controller into a single service file.&lt;/p&gt;

&lt;p&gt;A service that handles orders, payments, emails, inventory, user permissions, and reporting can become just as difficult to maintain.&lt;/p&gt;

&lt;p&gt;Organize code around meaningful responsibilities. An order service should coordinate order-related rules, while payment processing can have its own component when the complexity justifies it.&lt;/p&gt;

&lt;p&gt;Also, avoid adding interfaces and abstractions without a practical reason. A small application does not need a complicated architecture for every database operation.&lt;/p&gt;

&lt;p&gt;The right structure is the simplest one that keeps important rules understandable and reusable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch Out for Transaction Boundaries
&lt;/h2&gt;

&lt;p&gt;Order processing also illustrates why clean architecture alone is not enough.&lt;/p&gt;

&lt;p&gt;Suppose an application creates an order successfully but fails while reducing inventory. The database may end up with inconsistent records if related operations are not handled correctly.&lt;/p&gt;

&lt;p&gt;When several database changes must succeed together, a transaction can help preserve consistency. External actions, such as sending an email, need separate consideration because they cannot normally be rolled back by a database transaction.&lt;/p&gt;

&lt;p&gt;The architecture should make these boundaries explicit rather than hiding every operation inside a controller method.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Refactoring Strategy
&lt;/h2&gt;

&lt;p&gt;You do not need to rewrite the entire application.&lt;/p&gt;

&lt;p&gt;Start with one controller method that contains several business rules. Identify the decisions that belong to the business domain, move them into a focused service, and leave request handling in the controller.&lt;/p&gt;

&lt;p&gt;Then add tests around the extracted logic and compare the behavior with the original implementation.&lt;/p&gt;

&lt;p&gt;Repeat this process only where it improves clarity, testability, or reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Controllers are useful entry points, but they should not become the place where every business decision lives.&lt;/p&gt;

&lt;p&gt;Keeping business rules in focused components makes applications easier to test, change, and maintain. More importantly, it allows different parts of an application to follow the same rules without duplicating them.&lt;/p&gt;

&lt;p&gt;Good architecture is not about creating more folders. It is about making it clear where a decision belongs and ensuring that the decision remains consistent as the application grows.&lt;/p&gt;

&lt;p&gt;For more insights on maintainable web applications and search-friendly development practices, explore &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; This article was prepared with assistance from an AI writing tool and should be reviewed for technical accuracy before publication.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>architecture</category>
      <category>beginners</category>
    </item>
    <item>
      <title>It Works Locally, but Fails in Production: Debugging a Broken Form</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Sat, 24 Oct 2026 14:21:03 +0000</pubDate>
      <link>https://dev.to/buildforsearch/it-works-locally-but-fails-in-production-debugging-a-broken-form-10am</link>
      <guid>https://dev.to/buildforsearch/it-works-locally-but-fails-in-production-debugging-a-broken-form-10am</guid>
      <description>&lt;p&gt;You test a contact form on your local machine. You fill in the fields, click Submit, and the success message appears.&lt;/p&gt;

&lt;p&gt;Everything looks fine.&lt;/p&gt;

&lt;p&gt;Then the website goes live, and users start reporting that the form does nothing. Some submissions work, others fail, and your browser console does not always show an obvious error.&lt;/p&gt;

&lt;p&gt;Before blaming the hosting provider, take a step back. A form submission passes through several layers, and the failure could happen at any of them.&lt;/p&gt;

&lt;p&gt;Let's walk through how to investigate it without randomly changing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, Find Out What Actually Failed
&lt;/h2&gt;

&lt;p&gt;A common mistake is treating every failed form submission as a frontend problem.&lt;/p&gt;

&lt;p&gt;The browser might not send the request at all. The request might reach the server but return an error. The server might accept the data but fail while saving it. Or the request might succeed while the frontend incorrectly displays an error.&lt;/p&gt;

&lt;p&gt;These are different problems, and each requires a different fix.&lt;/p&gt;

&lt;p&gt;Open your browser's Network panel and submit the form again. Look for the request that should be triggered by the submission.&lt;/p&gt;

&lt;p&gt;If no request appears, investigate the event handler, validation logic, and JavaScript errors. If a request appears, inspect its URL, method, payload, response status, and response body.&lt;/p&gt;

&lt;p&gt;This simple distinction can save a lot of debugging time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Whether Production Uses the Correct API URL
&lt;/h2&gt;

&lt;p&gt;One issue that often appears after deployment is an incorrect environment variable.&lt;/p&gt;

&lt;p&gt;Your local application might send requests to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works on your computer because the API is running locally. But once the frontend is deployed, &lt;code&gt;localhost&lt;/code&gt; refers to the visitor's own device, not your development server.&lt;/p&gt;

&lt;p&gt;A better approach is to configure the API URL for each environment.&lt;/p&gt;

&lt;p&gt;For example, in a frontend build system that exposes environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitContactForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/contact`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Submission failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure &lt;code&gt;VITE_API_URL&lt;/code&gt; with the correct production API address in your deployment settings. Environment variables prefixed with &lt;code&gt;VITE_&lt;/code&gt; are exposed to client-side code, so never store private API secrets in them.&lt;/p&gt;

&lt;p&gt;Also check that the deployed application was rebuilt after changing its environment configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Investigate CORS and HTTPS
&lt;/h2&gt;

&lt;p&gt;Suppose the API URL is correct, but the browser still blocks the request.&lt;/p&gt;

&lt;p&gt;One possibility is a Cross-Origin Resource Sharing (CORS) issue. If your frontend and API use different origins, the server must allow the frontend origin when the request requires CORS permission.&lt;/p&gt;

&lt;p&gt;Check the browser console and Network panel for CORS errors. Fix the server's CORS configuration rather than trying to bypass browser security from frontend JavaScript.&lt;/p&gt;

&lt;p&gt;HTTPS can introduce another problem. If your website loads over HTTPS but attempts to call an HTTP API, the browser may block the request as mixed content.&lt;/p&gt;

&lt;p&gt;The production frontend and API should use an appropriate secure configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the UI Handle Failures Honestly
&lt;/h2&gt;

&lt;p&gt;A form should not display a success message simply because the submit button was clicked.&lt;/p&gt;

&lt;p&gt;It should wait for the server response and communicate the actual result. It should also prevent accidental repeated submissions while a request is in progress.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submitting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;submitContactForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contact form submission failed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;setStatus&lt;/code&gt; represents your application's state update function. The UI can use that state to show a loading indicator, a confirmation message, or an error that asks the user to try again.&lt;/p&gt;

&lt;p&gt;In a real application, also verify that the backend accepts the submitted data format. The example above uses &lt;code&gt;FormData&lt;/code&gt;, while the earlier JSON request example expects a JSON payload. Those formats must match your backend implementation.&lt;/p&gt;

&lt;p&gt;Avoid logging sensitive form contents or personal information to the browser console or server logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the Entire Flow Before Calling It Fixed
&lt;/h2&gt;

&lt;p&gt;Once the issue is resolved, test the form against the deployed environment, not only your local development server.&lt;/p&gt;

&lt;p&gt;Submit valid data, try invalid inputs, test the server's error response, and confirm that successful submissions actually reach their intended destination. Check the behavior on mobile devices as well.&lt;/p&gt;

&lt;p&gt;For additional investigation, the &lt;a href="https://developer.chrome.com/docs/devtools/network/" rel="noopener noreferrer"&gt;Chrome DevTools Network documentation&lt;/a&gt; explains how to inspect requests, response headers, payloads, and timing. The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS" rel="noopener noreferrer"&gt;MDN guide to CORS&lt;/a&gt; is also useful when cross-origin requests fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond One Form
&lt;/h2&gt;

&lt;p&gt;A broken contact form can quietly interrupt the path between a website visitor and a business inquiry. The same debugging approach applies to login forms, checkout flows, booking systems, and other interactions that depend on APIs.&lt;/p&gt;

&lt;p&gt;For teams working on &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;, reliable website functionality is an important part of delivering a useful experience. Search visibility alone cannot compensate for a form or navigation flow that fails when a visitor tries to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;When something works locally but fails in production, resist the urge to rewrite everything.&lt;/p&gt;

&lt;p&gt;Trace the request from the browser to the server, verify the environment configuration, inspect the actual response, and make sure the UI reflects what really happened.&lt;/p&gt;

&lt;p&gt;The fastest fix usually starts with identifying the failing layer, not guessing which line of code looks suspicious.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Your JavaScript Event Listener Isn't Firing? Check These 5 Things</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Tue, 20 Oct 2026 14:17:50 +0000</pubDate>
      <link>https://dev.to/buildforsearch/your-javascript-event-listener-isnt-firing-check-these-5-things-n7l</link>
      <guid>https://dev.to/buildforsearch/your-javascript-event-listener-isnt-firing-check-these-5-things-n7l</guid>
      <description>&lt;p&gt;You click a button, nothing happens, and the browser console shows no obvious error.&lt;/p&gt;

&lt;p&gt;If you have worked with JavaScript for a while, you have probably encountered this kind of bug. The button looks correct, the HTML is present, and the page loads normally, but the expected action never runs.&lt;/p&gt;

&lt;p&gt;Before rewriting the component or adding more event listeners, check a few common causes.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Make Sure the Element Exists When You Select It
&lt;/h2&gt;

&lt;p&gt;One of the simplest reasons an event listener fails is that JavaScript runs before the target element exists in the DOM.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#saveButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"saveButton"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on where the script runs, &lt;code&gt;querySelector()&lt;/code&gt; may return &lt;code&gt;null&lt;/code&gt;. Calling &lt;code&gt;addEventListener()&lt;/code&gt; on &lt;code&gt;null&lt;/code&gt; throws an error.&lt;/p&gt;

&lt;p&gt;One solution is to place the script after the HTML element. Another is to wait until the DOM has been parsed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#saveButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional chaining prevents an error if the element is missing, but it does not fix an incorrect selector. Check that the element actually exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Verify the Selector
&lt;/h2&gt;

&lt;p&gt;A small mismatch can silently prevent your code from selecting the intended element.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#save-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks for an element with the ID &lt;code&gt;save-button&lt;/code&gt;, not &lt;code&gt;saveButton&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the browser console and test the selector directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#saveButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the result is &lt;code&gt;null&lt;/code&gt;, inspect the HTML and confirm that the ID or class matches exactly. Also check whether the element is inside an iframe or a different document.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Check Whether Another Element Blocks the Click
&lt;/h2&gt;

&lt;p&gt;Sometimes the listener is correctly registered, but the click reaches another element instead.&lt;/p&gt;

&lt;p&gt;An invisible overlay, a modal backdrop, or an element with a higher stacking order can cover the button. CSS properties such as &lt;code&gt;pointer-events: none&lt;/code&gt; can also change how pointer interactions behave.&lt;/p&gt;

&lt;p&gt;Use the browser's Elements panel to inspect the layout and identify elements positioned over the button. Temporarily disabling suspicious styles can help isolate the problem.&lt;/p&gt;

&lt;p&gt;Do not assume every unresponsive button has a JavaScript issue. The cause may be in the CSS or page structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Understand Event Delegation
&lt;/h2&gt;

&lt;p&gt;If your buttons are created dynamically, attaching a listener to each button before it exists will not work.&lt;/p&gt;

&lt;p&gt;For example, a list may be rendered after an API request. Instead of registering a listener on every future button, you can listen on a parent element and inspect the clicked target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#results&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.result-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Result clicked:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern is called event delegation. It is useful when handling repeated elements that are added or replaced after the page initially loads.&lt;/p&gt;

&lt;p&gt;Make sure the parent exists and that the target selector matches the generated markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Look for Errors and Conflicting Logic
&lt;/h2&gt;

&lt;p&gt;If the listener appears to be registered correctly, inspect the Console and set a breakpoint inside the callback.&lt;/p&gt;

&lt;p&gt;Check whether an earlier error stops the relevant code from running. Also look for duplicate IDs, multiple handlers, unexpected &lt;code&gt;stopPropagation()&lt;/code&gt; calls, and form submissions that reload the page before you can observe the result.&lt;/p&gt;

&lt;p&gt;Chrome DevTools lets you inspect event listeners and pause JavaScript execution. The &lt;a href="https://developer.chrome.com/docs/devtools/" rel="noopener noreferrer"&gt;Chrome DevTools documentation&lt;/a&gt; is a useful starting point for learning these debugging tools.&lt;/p&gt;

&lt;p&gt;For more detail on event behavior, MDN's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Events" rel="noopener noreferrer"&gt;Event reference&lt;/a&gt; explains the events available to web applications and how they work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond One Button
&lt;/h2&gt;

&lt;p&gt;Small interaction bugs can make forms, navigation menus, filters, and checkout flows frustrating to use. For teams working on &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;, reliable interactions are part of building a website that people can use confidently.&lt;/p&gt;

&lt;p&gt;A broken event listener does not automatically affect search rankings, but broken navigation or unusable forms can undermine the experience a website is supposed to provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;When a JavaScript event listener does not fire, debug the full interaction path.&lt;/p&gt;

&lt;p&gt;Confirm that the element exists, verify the selector, check for overlays, consider dynamic content, and inspect the execution flow. These checks are usually faster and more reliable than randomly changing the code.&lt;/p&gt;

&lt;p&gt;The goal is not just to make the click work. It is to understand why it failed so the same bug is less likely to return.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Your Page Is Slow. Is It the API or the Frontend?</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Mon, 19 Oct 2026 14:50:58 +0000</pubDate>
      <link>https://dev.to/buildforsearch/your-page-is-slow-is-it-the-api-or-the-frontend-fai</link>
      <guid>https://dev.to/buildforsearch/your-page-is-slow-is-it-the-api-or-the-frontend-fai</guid>
      <description>&lt;p&gt;A page can look simple and still take forever to become usable.&lt;/p&gt;

&lt;p&gt;Maybe the spinner stays on screen too long. Maybe product cards appear one by one. Or everything loads, but clicking a button triggers another delay.&lt;/p&gt;

&lt;p&gt;The first instinct is often to optimize the frontend. But before changing components, reducing CSS, or adding another caching library, find out where the time is actually going.&lt;/p&gt;

&lt;p&gt;Sometimes the bottleneck is the API. Sometimes the browser is waiting on a chain of requests. And sometimes the server responds quickly, but the frontend takes too long to process the result.&lt;/p&gt;

&lt;p&gt;Here's a practical way to investigate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start With the Network Tab
&lt;/h2&gt;

&lt;p&gt;Open Chrome DevTools, select the &lt;strong&gt;Network&lt;/strong&gt; tab, and reload the page.&lt;/p&gt;

&lt;p&gt;Look for requests that take the longest. Pay attention to their status codes, response times, transferred sizes, and initiators.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.chrome.com/docs/devtools/network/" rel="noopener noreferrer"&gt;Chrome DevTools Network guide&lt;/a&gt; explains how to inspect requests, response headers, timing, and network activity.&lt;/p&gt;

&lt;p&gt;Don't assume the slowest request is automatically the root cause. Check whether the page is waiting for it before rendering important content.&lt;/p&gt;

&lt;p&gt;For example, if a dashboard waits for five unrelated API calls to finish before showing anything, the user experience may be slower than necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Check Whether Requests Are Running in Series
&lt;/h2&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/orders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each request waits for the previous one to finish. If these requests are independent, that adds unnecessary waiting time.&lt;/p&gt;

&lt;p&gt;You could run them concurrently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/orders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can reduce total waiting time when the requests do not depend on each other.&lt;/p&gt;

&lt;p&gt;One important detail: &lt;code&gt;fetch()&lt;/code&gt; does not reject automatically for HTTP errors such as 404 or 500. Check &lt;code&gt;response.ok&lt;/code&gt; before using the returned data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Request failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use concurrent requests only when the data dependencies allow it. If one request requires the result of another, keep that dependency explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Separate Server Time From Browser Work
&lt;/h2&gt;

&lt;p&gt;A slow page does not always mean the API is slow.&lt;/p&gt;

&lt;p&gt;Check the request timing in DevTools. If the browser spends a long time waiting for the response to begin, investigate the server, database queries, upstream services, and network latency.&lt;/p&gt;

&lt;p&gt;If the response arrives quickly but the interface remains unresponsive, inspect frontend rendering, long JavaScript tasks, and unnecessary component updates.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.chrome.com/docs/devtools/network/reference/" rel="noopener noreferrer"&gt;Chrome DevTools Network reference&lt;/a&gt; explains how to examine request timing, response sizes, and the network waterfall.&lt;/p&gt;

&lt;p&gt;That distinction matters because optimizing database queries will not fix an expensive rendering loop, just as memoizing React components will not fix a slow backend endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Handle Failures Without Freezing the UI
&lt;/h2&gt;

&lt;p&gt;A request can fail because of a timeout, server error, connectivity issue, or unexpected response format.&lt;/p&gt;

&lt;p&gt;Make sure the interface has a clear loading state, an error state, and a way to retry when appropriate.&lt;/p&gt;

&lt;p&gt;For example, don't leave a spinner running forever after a failed request. Show a useful message and preserve any information the user has already entered.&lt;/p&gt;

&lt;p&gt;Be careful with automatic retries. Retrying every failed request immediately can increase server load, and repeating a non-idempotent operation such as a payment submission may cause unintended results.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Measure Before and After
&lt;/h2&gt;

&lt;p&gt;Once you've made a change, repeat the same test under comparable conditions.&lt;/p&gt;

&lt;p&gt;Check whether the request count decreased, whether the critical API response became faster, and whether users can interact with the page sooner.&lt;/p&gt;

&lt;p&gt;Test on a slower network as well. A page that feels instant on a developer's machine may behave differently on a mobile connection.&lt;/p&gt;

&lt;p&gt;For teams working on &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;, connecting technical website quality with the overall user experience is an important part of building a reliable online presence. RankifyDev offers website development and SEO services for businesses that want to improve their websites and search visibility. Whatever approach you choose, focus on measurable issues rather than making changes just to chase a perfect score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;When a page feels slow, resist the urge to rewrite the frontend immediately.&lt;/p&gt;

&lt;p&gt;Start with the Network tab, identify the requests that matter, and separate backend latency from browser work. Then make one targeted change and measure the result.&lt;/p&gt;

&lt;p&gt;A little investigation usually gives you a better direction than guessing which part of the stack needs optimization.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Your Website Feels Slow? Start With These 4 Performance Fixes</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:26:00 +0000</pubDate>
      <link>https://dev.to/buildforsearch/your-website-feels-slow-start-with-these-4-performance-fixes-3h0p</link>
      <guid>https://dev.to/buildforsearch/your-website-feels-slow-start-with-these-4-performance-fixes-3h0p</guid>
      <description>&lt;p&gt;A website does not need to be completely broken to frustrate visitors. Sometimes the page loads, but the main image takes too long to appear. A button feels unresponsive, or the layout suddenly shifts just as someone tries to click something.&lt;/p&gt;

&lt;p&gt;These problems are easy to overlook during development because a website may feel fast on your own laptop and office Wi-Fi.&lt;/p&gt;

&lt;p&gt;The better approach is to measure performance, identify the actual bottleneck, and fix the problems that matter most to users.&lt;/p&gt;

&lt;p&gt;For developers working on &lt;strong&gt;Web Development SEO&lt;/strong&gt;, performance optimization should be part of building a reliable website, not just a final step before launch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzn3dczdh6324t5xyznrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzn3dczdh6324t5xyznrd.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Find Out What Is Actually Slow
&lt;/h2&gt;

&lt;p&gt;Before changing code, run your page through &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt; and inspect the results.&lt;/p&gt;

&lt;p&gt;Pay attention to three Core Web Vitals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Largest Contentful Paint (LCP):&lt;/strong&gt; How quickly the main visible content appears.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interaction to Next Paint (INP):&lt;/strong&gt; How responsive the page feels when users interact with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumulative Layout Shift (CLS):&lt;/strong&gt; How much the page layout moves unexpectedly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a good user experience, the current recommended thresholds are LCP of 2.5 seconds or less, INP of 200 milliseconds or less, and CLS of 0.1 or less, measured at the 75th percentile of page loads.&lt;/p&gt;

&lt;p&gt;Do not treat a single Lighthouse score as the complete picture. Lab tests help diagnose problems, while real-user field data shows how the website performs across different devices and network conditions.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://web.dev/performance/" rel="noopener noreferrer"&gt;web.dev performance guide&lt;/a&gt; explains how to measure performance and find suitable optimization opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Optimize the Main Image First
&lt;/h2&gt;

&lt;p&gt;Large hero images are a common reason why the most important content takes too long to appear.&lt;/p&gt;

&lt;p&gt;A developer might optimize JavaScript and CSS while leaving a huge, uncompressed image at the top of the page. The page can still feel slow because the main visual content arrives late.&lt;/p&gt;

&lt;p&gt;Start with these checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize images to dimensions appropriate for their display size.&lt;/li&gt;
&lt;li&gt;Use modern formats such as WebP or AVIF when suitable.&lt;/li&gt;
&lt;li&gt;Compress images without making them visibly poor quality.&lt;/li&gt;
&lt;li&gt;Avoid lazy-loading the main above-the-fold image when it is the LCP element.&lt;/li&gt;
&lt;li&gt;Use lazy loading for suitable images further down the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a below-the-fold image can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/team.webp"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Our development team"&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The width and height attributes help the browser reserve space for the image, reducing unexpected layout movement. The &lt;code&gt;alt&lt;/code&gt; text should describe the image meaningfully, rather than simply repeating keywords.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Reduce Unnecessary JavaScript
&lt;/h2&gt;

&lt;p&gt;Modern websites often include libraries, analytics scripts, animations, and components that are not needed immediately.&lt;/p&gt;

&lt;p&gt;Too much JavaScript can delay rendering and keep the main thread busy, making buttons and other interactions feel sluggish.&lt;/p&gt;

&lt;p&gt;Instead of removing packages randomly, use Chrome DevTools to inspect what is loading and executing.&lt;/p&gt;

&lt;p&gt;Consider these improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove unused dependencies and scripts.&lt;/li&gt;
&lt;li&gt;Split large bundles so routes load only the code they need.&lt;/li&gt;
&lt;li&gt;Defer non-critical work where appropriate.&lt;/li&gt;
&lt;li&gt;Avoid running expensive calculations during user interactions.&lt;/li&gt;
&lt;li&gt;Load third-party scripts only when they are genuinely needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a React application, route-level code splitting can prevent every page from downloading the full application bundle before the user needs it.&lt;/p&gt;

&lt;p&gt;The important point is to measure before and after each change. Smaller JavaScript bundles can help, but the real improvement depends on how your application uses that code.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Stop Unexpected Layout Shifts
&lt;/h2&gt;

&lt;p&gt;Have you ever tried clicking a button and watched it move because an advertisement, image, or banner appeared above it?&lt;/p&gt;

&lt;p&gt;That is the kind of experience CLS is designed to measure.&lt;/p&gt;

&lt;p&gt;Reserve space for images, videos, and other elements that load asynchronously. Avoid inserting new content above existing content unless it is triggered by a user action. Be careful with web fonts that significantly change text dimensions after loading.&lt;/p&gt;

&lt;p&gt;For example, defining image dimensions gives the browser a better idea of the space the image will occupy before it finishes downloading.&lt;/p&gt;

&lt;p&gt;Also test cookie banners, promotional bars, and embedded widgets. They can create layout shifts even when the rest of the page is well optimized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure the Result, Not Just the Score
&lt;/h2&gt;

&lt;p&gt;After making changes, test the same page again under comparable conditions.&lt;/p&gt;

&lt;p&gt;Look at which metric improved and whether the change affected other parts of the experience. Then review field data when enough real-user measurements are available.&lt;/p&gt;

&lt;p&gt;Developers working on &lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt; can explore RankifyDev for website development and SEO services that consider technical website quality alongside search visibility. Whatever approach you choose, prioritize measurable problems rather than making changes just to chase a perfect score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Website performance is not about applying every optimization you find online. It is about understanding what is slowing your particular website down.&lt;/p&gt;

&lt;p&gt;Start with measurement, optimize the main content, reduce unnecessary JavaScript, and prevent unexpected layout shifts. Test your changes and keep monitoring the experience after launch.&lt;/p&gt;

&lt;p&gt;Small, targeted improvements can make a website feel more reliable without requiring a complete rebuild.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; This article was prepared with AI assistance. Review the technical recommendations, verify the examples, and adapt the content to your own experience before publishing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>seo</category>
    </item>
    <item>
      <title>Web Development SEO: How to Build a Reliable XML Sitemap for a JavaScript Website</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Fri, 16 Oct 2026 15:04:47 +0000</pubDate>
      <link>https://dev.to/buildforsearch/web-development-seo-how-to-build-a-reliable-xml-sitemap-for-a-javascript-website-52oc</link>
      <guid>https://dev.to/buildforsearch/web-development-seo-how-to-build-a-reliable-xml-sitemap-for-a-javascript-website-52oc</guid>
      <description>&lt;p&gt;A website can have useful pages, clean URLs, and a well-organized navigation system, yet some pages may still be difficult for search engines to discover.&lt;/p&gt;

&lt;p&gt;This is especially worth checking on JavaScript websites, where routes may be generated dynamically and new pages can be added without changing the main navigation.&lt;/p&gt;

&lt;p&gt;An XML sitemap provides search engines with a list of URLs that a website owner considers important. It does not guarantee indexing, but it can help search engines discover eligible pages.&lt;/p&gt;

&lt;p&gt;For developers working on &lt;strong&gt;&lt;a href="https://rankifydev.com/" rel="noopener noreferrer"&gt;Web Development SEO&lt;/a&gt;&lt;/strong&gt;, generating and maintaining a correct sitemap should be part of the website's technical setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz27scvjo8p3op7kc0642.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz27scvjo8p3op7kc0642.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand What Belongs in a Sitemap
&lt;/h2&gt;

&lt;p&gt;An XML sitemap should contain the canonical URLs of pages that you want search engines to discover.&lt;/p&gt;

&lt;p&gt;For example, a website might include URLs for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main service pages&lt;/li&gt;
&lt;li&gt;Important product pages&lt;/li&gt;
&lt;li&gt;Published blog posts&lt;/li&gt;
&lt;li&gt;Useful category pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, not every URL belongs in the sitemap.&lt;/p&gt;

&lt;p&gt;Avoid including URLs that redirect, return errors, are blocked from indexing, or are duplicates of another preferred URL.&lt;/p&gt;

&lt;p&gt;Consider a website with these routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
 /services
 /services/web-development
 /blog
 /blog/website-performance
 /login
 /search?q=seo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The homepage, service pages, and published article may be appropriate sitemap entries. The login page and parameter-based search URL should be evaluated separately and generally should not be included unless there is a specific reason they are intended for search.&lt;/p&gt;

&lt;p&gt;The important rule is simple: include the URLs that you actually want search engines to consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Generate Valid XML
&lt;/h2&gt;

&lt;p&gt;A basic XML sitemap looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;urlset&lt;/span&gt;
  &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.sitemaps.org/schemas/sitemap/0.9"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;https://example.com/&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;https://example.com/services&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;https://example.com/services/web-development&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;https://example.com/blog/website-performance&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/urlset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the example URLs with real canonical URLs from your website.&lt;/p&gt;

&lt;p&gt;Notice that each URL uses the complete HTTPS address. The XML structure must also be valid, with correctly opened and closed elements.&lt;/p&gt;

&lt;p&gt;For production websites, generate this file from the same source that manages your published pages rather than maintaining a long list manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generate the Sitemap From Your Application Data
&lt;/h2&gt;

&lt;p&gt;For a JavaScript application, sitemap generation can be connected to your content management system, database, or static route configuration.&lt;/p&gt;

&lt;p&gt;For example, a simplified Node.js function could generate XML from a list of approved URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;escapeXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;amp;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;amp;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/"/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/'/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;apos;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateSitemap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`
  &amp;lt;url&amp;gt;
    &amp;lt;loc&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;escapeXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/loc&amp;gt;
  &amp;lt;/url&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&amp;lt;/urlset&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/services&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/blog/website-performance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sitemap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateSitemap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sitemap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a minimal illustration, not a complete production implementation. In a real project, validate each URL against an approved route or content record, exclude non-indexable pages, and write the generated XML to the correct public location.&lt;/p&gt;

&lt;p&gt;Do not build the sitemap from every URL that happens to appear in application logs or user-generated input.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Keep the Sitemap Updated
&lt;/h2&gt;

&lt;p&gt;A sitemap becomes less useful when it contains outdated URLs.&lt;/p&gt;

&lt;p&gt;Imagine that a developer publishes a new article but forgets to add it to a manually maintained sitemap. The page might still be discovered through internal links, but the sitemap would no longer represent the current website accurately.&lt;/p&gt;

&lt;p&gt;A better approach is to generate sitemap entries from published content.&lt;/p&gt;

&lt;p&gt;When a page is published, it can become eligible for inclusion. When a page is permanently removed, its URL should be removed from the sitemap. When a URL changes, update the sitemap to use the new canonical URL and configure an appropriate redirect if necessary.&lt;/p&gt;

&lt;p&gt;For a large website, consider splitting the sitemap into multiple files and using a sitemap index when the documented limits require it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make the Sitemap Publicly Accessible
&lt;/h2&gt;

&lt;p&gt;After generating the file, make sure it is available at a predictable URL, commonly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the response in a browser or with a command-line tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint should return the expected successful HTTP status rather than a redirect loop, server error, or HTML page generated by the frontend application.&lt;/p&gt;

&lt;p&gt;If your application uses a fallback route that serves &lt;code&gt;index.html&lt;/code&gt; for unknown URLs, verify that &lt;code&gt;/sitemap.xml&lt;/code&gt; is handled correctly. A sitemap URL that returns the website's HTML is not a valid XML sitemap.&lt;/p&gt;

&lt;p&gt;You can also reference the sitemap in your &lt;code&gt;robots.txt&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: *
Allow: /

Sitemap: https://example.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example assumes that the site does not need additional crawling restrictions. Do not copy the &lt;code&gt;Allow&lt;/code&gt; rule blindly if your project has specific robots directives.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Validate Before Submitting
&lt;/h2&gt;

&lt;p&gt;Before considering the sitemap complete, check the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every listed URL belongs to the correct domain.&lt;/li&gt;
&lt;li&gt;URLs use HTTPS when that is the site's canonical protocol.&lt;/li&gt;
&lt;li&gt;Pages return the expected HTTP status.&lt;/li&gt;
&lt;li&gt;Redirecting and broken URLs are excluded.&lt;/li&gt;
&lt;li&gt;Canonical URLs are used consistently.&lt;/li&gt;
&lt;li&gt;XML syntax is valid.&lt;/li&gt;
&lt;li&gt;Important pages are not accidentally excluded.&lt;/li&gt;
&lt;li&gt;The sitemap updates when published content changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then submit the sitemap through Google Search Console and review any reported errors.&lt;/p&gt;

&lt;p&gt;Google's official &lt;a href="https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview" rel="noopener noreferrer"&gt;sitemap documentation&lt;/a&gt; explains how to create, manage, and submit sitemaps.&lt;/p&gt;

&lt;p&gt;Remember that submission is a discovery signal, not a guarantee that every listed URL will be crawled or indexed. Search engines still decide which pages to index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;A sitemap is a small technical component, but it becomes important when a website has many routes, frequently updated content, or a JavaScript-based architecture.&lt;/p&gt;

&lt;p&gt;Developers can make sitemap management more reliable by generating URLs from trusted content data, validating the output, and updating it automatically when pages change.&lt;/p&gt;

&lt;p&gt;As part of a broader Web Development SEO workflow, this simple practice helps keep a website's discovery signals organized and reduces avoidable sitemap errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; This article was prepared with AI assistance. Review the technical examples, test them against your own application, and make sure you understand the implementation before publishing.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Web Development SEO: How to Measure Real Website Performance With Core Web Vitals</title>
      <dc:creator>Build for Search</dc:creator>
      <pubDate>Thu, 15 Oct 2026 15:11:54 +0000</pubDate>
      <link>https://dev.to/buildforsearch/web-development-seo-how-to-measure-real-website-performance-with-core-web-vitals-2eb2</link>
      <guid>https://dev.to/buildforsearch/web-development-seo-how-to-measure-real-website-performance-with-core-web-vitals-2eb2</guid>
      <description>&lt;p&gt;A website can score well in a local performance test and still feel slow to some visitors.&lt;/p&gt;

&lt;p&gt;Why does this happen? Testing conditions differ. A developer might have a fast laptop, a reliable internet connection, and a warm browser cache. A visitor might use a mid-range phone, a slower network, or a page that has never been loaded before.&lt;/p&gt;

&lt;p&gt;This is why web development SEO should not rely on a single performance score. Developers need to understand both lab measurements and real-user data.&lt;/p&gt;

&lt;p&gt;Core Web Vitals provide a useful way to evaluate three important parts of the user experience: loading performance, responsiveness, and visual stability.&lt;/p&gt;

&lt;p&gt;Let's look at how to measure them and use the results to guide improvements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxp8a26rw6r2e1ivht1t6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxp8a26rw6r2e1ivht1t6.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand the Three Core Web Vitals
&lt;/h2&gt;

&lt;p&gt;Before changing code, understand what each metric measures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Largest Contentful Paint (LCP)&lt;/strong&gt; measures how quickly the main content becomes visible. A good LCP result is 2.5 seconds or less.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interaction to Next Paint (INP)&lt;/strong&gt; measures how responsive a page is to user interactions throughout a visit. A good INP result is 200 milliseconds or less.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt; measures unexpected movement of visible page elements. A good CLS score is 0.1 or less.&lt;/p&gt;

&lt;p&gt;These thresholds apply at the 75th percentile of real visits, with mobile and desktop evaluated separately.&lt;/p&gt;

&lt;p&gt;The metrics describe different problems. A page can load quickly but respond slowly to clicks. Another page might respond immediately but move its content around while images load.&lt;/p&gt;

&lt;p&gt;Treat each metric as a separate diagnostic signal rather than trying to optimize one score in isolation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understand Lab Data and Field Data
&lt;/h2&gt;

&lt;p&gt;Lab data comes from controlled tests, such as Lighthouse. It is useful when you need to reproduce a problem, inspect network requests, or test a code change.&lt;/p&gt;

&lt;p&gt;Field data comes from real users interacting with your website under different conditions. It helps reveal performance issues that may not appear in a local test.&lt;/p&gt;

&lt;p&gt;For example, your development machine might load a large hero image quickly. Visitors using slower mobile connections may experience a much longer delay.&lt;/p&gt;

&lt;p&gt;Both types of data are useful, but they answer different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lab data helps investigate what might be causing a problem.&lt;/li&gt;
&lt;li&gt;Field data helps you understand what users actually experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use lab tests to investigate issues and field data to check whether the experience is consistently good for visitors.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Collect Core Web Vitals With JavaScript
&lt;/h2&gt;

&lt;p&gt;If you want to monitor performance within your own application, the &lt;code&gt;web-vitals&lt;/code&gt; JavaScript library provides a straightforward starting point.&lt;/p&gt;

&lt;p&gt;Install the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;web-vitals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a small reporting module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onCLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onINP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onLCP&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;web-vitals&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reportMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;onCLS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportMetric&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;onINP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportMetric&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;onLCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportMetric&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example reports metric objects to the browser console. It is useful for initial testing, but console output alone is not a production monitoring system.&lt;/p&gt;

&lt;p&gt;In a production application, send the measurements to an analytics endpoint or monitoring service. Avoid collecting unnecessary personal information, and make sure the reporting mechanism follows your privacy requirements.&lt;/p&gt;

&lt;p&gt;You can then group results by metric, page type, device category, or release version to identify patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Connect Measurements to Actual Problems
&lt;/h2&gt;

&lt;p&gt;Collecting metrics is only the first step. The next task is to understand what causes poor results.&lt;/p&gt;

&lt;p&gt;If LCP is slow, inspect the largest visible element. It may be a large image, a delayed server response, or a resource that is discovered too late.&lt;/p&gt;

&lt;p&gt;If INP is poor, use browser performance tools to investigate long JavaScript tasks, expensive event handlers, or unnecessary rendering work.&lt;/p&gt;

&lt;p&gt;If CLS is high, look for images without reserved dimensions, dynamically injected content, or elements that change size after the page appears.&lt;/p&gt;

&lt;p&gt;Avoid making changes based on assumptions. Identify the likely cause, change one important thing, and measure again.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Check Performance Across Important Page Types
&lt;/h2&gt;

&lt;p&gt;A website rarely consists of only one page template.&lt;/p&gt;

&lt;p&gt;A homepage might use a large hero image, while a product page may contain interactive controls and a service page may rely on several embedded components.&lt;/p&gt;

&lt;p&gt;Test representative pages rather than assuming that one successful homepage test means the whole website performs well.&lt;/p&gt;

&lt;p&gt;For websites with enough real-user data, Google Search Console's Core Web Vitals report can help identify URL groups with performance problems. PageSpeed Insights can provide additional diagnostic information for individual URLs.&lt;/p&gt;

&lt;p&gt;If a report has insufficient field data, that does not automatically mean the page performs badly. Use lab testing and other available evidence until enough real-user data becomes available.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Treat Performance as an Ongoing Development Task
&lt;/h2&gt;

&lt;p&gt;Performance can change when new dependencies are introduced, images are replaced, scripts are added, or layouts are redesigned.&lt;/p&gt;

&lt;p&gt;Include basic performance checks in your development workflow. Test important page templates after significant changes, monitor real-user data where available, and prioritize problems based on their impact.&lt;/p&gt;

&lt;p&gt;Do not chase a perfect laboratory score at the expense of useful functionality. The goal is to create a responsive, stable experience that works well for real visitors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Web development SEO is stronger when performance decisions are based on evidence instead of assumptions.&lt;/p&gt;

&lt;p&gt;Use lab tools to investigate problems, real-user data to understand visitor experiences, and Core Web Vitals to identify issues with loading, responsiveness, and layout stability.&lt;/p&gt;

&lt;p&gt;Measure first, fix the most important bottleneck, and test again. This approach makes performance work more focused and helps developers build websites that are both technically sound and easier to use.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This article was prepared with AI assistance and should be reviewed for technical accuracy before publication.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
