Skip to content

Content Distribution in Vue JS

Content Distribution in Vue JS

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Vue implements a content distribution API inspired by the Web Components spec draft, using the <slot> element to serve as distribution outlets for content.

It promotes building composable and reusable components. Many folks have been writing about, or discussing, best practices, how to build components, how they communicate with each other, and how they should be structured in an app.

In this article, we'll dive head-first into Vue.js Slots, and Scoped Slots concepts, and go through code samples.

##Slots A Slot is a placeholder that allows content projection from a parent component to a child component.

The Vue engine, at runtime, processes the parent template, pulls the dynamic content, and injects it inside the Slot placeholder in the child component. In general, the child component hosts the <slot> element, and the parent component specifies the content to go inside it.

Figure 1 shows the interaction between a parent and child component.

|Parent and child component

Figure 1: Parent and child component

Basically, Slots are used for building Layout components (also known as Master Pages), base components (Button, Hyperlink and the like) or any other type of composable components to provide flexibility for component consumers to inject dynamic content at runtime.

Let’s create a Button component with a <slot> element.

<template>
  <button>
    <slot>Click Me</slot>
  </button>
</template>

The Button component is basic and contains a single <button> element. The button wraps a <slot> component with a default fallback text. This means, if the parent component didn’t provide any content for the Slot, it will be replaced at runtime with the default fallback text Click Me.

Let's embed this Button component inside a parent component.

<template>
    <Button></Button>
</template>

The child component Button is embedded into the parent component like any other normal component in Vue.js. Notice that in the code snippet above, the parent component is not injecting any content. When you run the app, you will see an HTML <button> element with the default fallback text. Figure 2 shows the app running.

Slot with default content
Figure 2: Slot with default content

Let's inject some other text instead of the default fallback text, and run the app again. You have multiple choices when it comes to injecting content.

Without <template> element

<Button>
  Pretty Nice Button!
</Button>

With <template> element

<Button>
  <template v-slot:default>
    Pretty Nice Button!
  </template>
</Button>

Personally, I prefer the option using <template> element. The template content will be rendered in place of the <slot> element.

The <slot> element has a special attribute called name. This allows you to embed multiple Slots in your component, each designated with a different Slot name.

A <slot> element without a name attribute is considered the default Slot. To provide content for a <slot> element, you would use the v-slot directive, and then specify the name of the Slot.

In this code snippet, we could have removed the v-slot:default as this is the only <slot> element in the component. But, as a best practice, and in case you add more Slots in the future, I’d recommend you stick to this naming convention by using the v-slot:default.

You can play with this example on codesandbox.io.

Let's assume the Button component has another slot:

<template>
  <button>
    <slot>Click Me</slot>
    <br>
    <slot name="footer"/>
  </button>
</template>

Inside the parent component:

<template>
    <Button>
      <template v-slot:default>Pretty Nice Button!</template>
      <template v-slot:footer>Footer!</template>
    </Button>
</template>

There are two <template> elements, each for a specific slot.To add content to the default <slot> element, you add the v-slot:default directive by specifying the name of the slot. For the footer Slot, you provide the v-slot:footer directive to target the footer <slot> element.

Now, it makes more sense to use the v-slot directive on both Slots to differentiate them, and make your code readable.

You can play with this example on codesandbox.io.

##Slots and Props Thus far, we have seen how to use <slot> elements, and inject content to them. In some other cases, you might need to pass data to Slots.

Slots are generally compiled under the parent’s component context. This means whatever content you project inside a <slot> element is aware of the parent’s context only. For instance, if you have an interpolation or binding projected inside the <slot> element, these will be compiled with respect to the parent component, and not the child component. A code snippet is worth a thousand words.

<template>
    <Button>
      <template v-slot:default>
        {{ text }}
      </template>
    </Button>
</template>

<script>
import Button from "./components/Button";

export default {
  components: {
    Button
  },
  data() {
    return {
      text: 'Pretty Nice Button!',
    };
  },
};
</script>

The {{ text }} interpolation is referencing a local data variable defined on the component named text. The Vue.js engine compiles the projected content inside the parent component scope, and embeds the results into the child component.

You can play with this example on codesandbox.io.

A <slot> element can also render default fallback text passed from the parent component to the child component. How? Nothing special really. It's similar to how you pass data to Vue components via props.

Let's introduce a new text property on the Button component:

<template>
  <button>
    <slot>{{ text }}</slot>
  </button>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      default: "Click Me"
    }
  }
};
</script>

In the parent component:

<template>
  <div id="app">
    <h2>Vue Slots Demo</h2>
    <Button v-bind:text="text"></Button>
  </div>
</template>

<script>
import Button from "./components/Button";

export default {
  components: {
    Button
  },
  data() {
    return {
      text: "Pretty Nice Button!!!!"
    };
  }
};
</script>

You make use of Vue.js binding convention to bind the text prop on Button component to a local variable also named text. That’s all!

You can play with this example on codesandbox.io.

You can even go wild and accept a prop of type Function on the child component! The child component can share its context with the parent component. The parent component can then manipulate the child component context and return whatever content back to the child component.

The child component accepts a prop of type Function:

<template>
  <button>
    <slot>{{ textFnc('Hi from child!') }}</slot>
  </button>
</template>

<script>
export default {
  props: {
    textFnc: {
      type: Function
    }
  }
};
</script>

The default fallback content inside the child component calls the prop Function passing some random text.

The parent component defines the prop Function as follows:

<template>
  <div id="app">
    <h2>Vue Slots Demo</h2>
    <Button v-bind:textFnc="(prefix) => prefix + ' - ' + message"></Button>
  </div>
</template>

<script>
import Button from "./components/Button";

export default {
  components: {
    Button
  },
  data() {
    return {
      message: "Pretty Nice Button!!!!"
    };
  }
};
</script>

The function textFunc() executes under the parent component context. In this case, the function returns the text received from the child component, and appends it to a message that’s local to the parent component. The end result is shown in Figure 3.

Function Prop
Figure 3: Function prop

You can play with this example on codesandbox.io.

The takeaway, in using functions as props, is the ability to share the child component’s context with the parent component.

##Scoped Slots Passing functions as props to a child component is one way of sharing context between child and parent components. However, this method is limited to text only. The function defined on the parent component can only return text.

What if you want the parent component to pass HTML content to the child component’s slot(s) and also make use of the child component context? This is where Scoped Slots play their part.

Pretty complicated right? Well, not as complicated as you might think. Let’s check it out together!

Let's build a List component that owns an array of objects with a title and description properties.

<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      <slot :item="item">
        <p>
          {{ item['title'] }}
          <br>
          {{ item['description'] }}
        </p>
      </slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    items: {
      type: Array,
      default: () => []
    }
  }
};
</script>

The component uses a <ul> element to loop over the items in the array. An <li> element is used to represent a single item. The code places a <slot> element inside each and every <li> element. The slot is bound to the single item object. In addition, the <slot> element defines a default fallback content.

Let’s switch to the parent component:

<template>
  <div id="app">
    <h2>Vue Slots Demo</h2>
    <List :items="items" />
  </div>
</template>

<script>
import List from "./components/List";

export default {
  components: {
    List
  },
  data() {
    return {
      items: [
        {
          id: 1,
          title: "Item #1",
          description: "Item #1 description"
        },
        {
          id: 2,
          title: "Item #2",
          description: "Item #2 description"
        },
        {
          id: 3,
          title: "Item #3",
          description: "Item #3 description"
        },
        {
          id: 4,
          title: "Item #4",
          description: "Item #4 description"
        },
        {
          id: 5,
          title: "Item #5",
          description: "Item #5 description"
        }
      ]
    };
  }
};
</script>

The component binds the items array property to the List component property items. It uses the default fallback content coming from the child component.

Figure 4 shows the app running:

List component with default fallback content
Figure 4: List component with default fallback content

Let’s see how we can make use of the Slot binding.

As a refresher, the child component defines the following:

<slot :item="item">
  <p>
    {{ item['title'] }}
    <br>
    {{ item['description'] }}
  </p>
</slot>

The <slot> element binds the item object on the Slot. It also provides a default fallback content. What if the parent component wants to replace this default content with a new content? That's easy!

Let's change the parent component as follows:

<template>
  <List :items="items">
    <template v-slot:default="prop">
      <strong>{{ prop.item.title }}</strong>
    </template>
  </List>
</template>

The code snippet provides a <template> with a v-slot:default directive. The value given to the v-slot:default directive is actually the directive value representing the object passed in by the <slot> element defined inside the child component.

As a side note, I am writing another article, to be published very soon, exploring custom directives in Vue.js. Stay tuned!

Going back to the code snippet, the parent component now has access to the child component represented by the v-slot:default directive value.

The <template> element replaces the default fallback content by rendering just the title field and making it bold.

Figure 5 shows the app running:

List component with custom content
Figure 5: List component with custom content

Scoped Slots is a powerful tool in Vue.js to allow you to build composable and reusable components.

##Slots in Vue 3 The content on Slots and Scoped Slots in this article applies to both Vue 2 and Vue 3. I am not aware of any change up until this moment. Things might change with the final release of Vue 3, but we’ll have to wait and see together!

##Conclusion Vue Slots feature gives developers the flexibility needed to build reusable and composable components in their applications.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

Incremental Hydration in Angular cover image

Incremental Hydration in Angular

Incremental Hydration in Angular Some time ago, I wrote a post about SSR finally becoming a first-class citizen in Angular. It turns out that the Angular team really treats SSR as a priority, and they have been working tirelessly to make SSR even better. As the previous blog post mentioned, full-page hydration was launched in Angular 16 and made stable in Angular 17, providing a great way to improve your Core Web Vitals. Another feature aimed to help you improve your INP and other Core Web Vitals was introduced in Angular 17: deferrable views. Using the @defer blocks allows you to reduce the initial bundle size and defer the loading of heavy components based on certain triggers, such as the section entering the viewport. Then, in September 2024, the smart folks at Angular figured out that they could build upon those two features, allowing you to mark parts of your application to be server-rendered dehydrated and then hydrate them incrementally when needed - hence incremental hydration. I’m sure you know what hydration is. In short, the server sends fully formed HTML to the client, ensuring that the user sees meaningful content as quickly as possible and once JavaScript is loaded on the client side, the framework will reconcile the rendered DOM with component logic, event handlers, and state - effectively hydrating the server-rendered content. But what exactly does "dehydrated" mean, you might ask? Here's what will happen when you mark a part of your application to be incrementally hydrated: 1. Server-Side Rendering (SSR): The content marked for incremental hydration is rendered on the server. 2. Skipped During Client-Side Bootstrapping: The dehydrated content is not initially hydrated or bootstrapped on the client, reducing initial load time. 3. Dehydrated State: The code for the dehydrated components is excluded from the initial client-side bundle, optimizing performance. 4. Hydration Triggers: The application listens for specified hydration conditions (e.g., on interaction, on viewport), defined with a hydrate trigger in the @defer block. 5. On-Demand Hydration: Once the hydration conditions are met, Angular downloads the necessary code and hydrates the components, allowing them to become interactive without layout shifts. How to Use Incremental Hydration Thanks to Mark Thompson, who recently hosted a feature showcase on incremental hydration, we can show some code. The first step is to enable incremental hydration in your Angular application's appConfig using the provideClientHydration provider function: ` Then, you can mark the components you want to be incrementally hydrated using the @defer block with a hydrate trigger: ` And that's it! You now have a component that will be server-rendered dehydrated and hydrated incrementally when it becomes visible to the user. But what if you want to hydrate the component on interaction or some other trigger? Or maybe you don't want to hydrate the component at all? The same triggers already supported in @defer blocks are available for hydration: - idle: Hydrate once the browser reaches an idle state. - viewport: Hydrate once the component enters the viewport. - interaction: Hydrate once the user interacts with the component through click or keydown triggers. - hover: Hydrate once the user hovers over the component. - immediate: Hydrate immediately when the component is rendered. - timer: Hydrate after a specified time delay. - when: Hydrate when a provided conditional expression is met. And on top of that, there's a new trigger available for hydration: - never: When used, the component will remain static and not hydrated. The never trigger is handy when you want to exclude a component from hydration altogether, making it a completely static part of the page. Personally, I'm very excited about this feature and can't wait to try it out. How about you?...

Next.js + MongoDB Connection Storming cover image

Next.js + MongoDB Connection Storming

Building a Next.js application connected to MongoDB can feel like a match made in heaven. MongoDB stores all of its data as JSON objects, which don’t require transformation into JavaScript objects like relational SQL data does. However, when deploying your application to a serverless production environment such as Vercel, it is crucial to manage your database connections properly. If you encounter errors like these, you may be experiencing Connection Storming: * MongoServerSelectionError: connect ECONNREFUSED &lt;IP_ADDRESS>:&lt;PORT> * MongoNetworkError: failed to connect to server [&lt;hostname>:&lt;port>] on first connect * MongoTimeoutError: Server selection timed out after &lt;x> ms * MongoTopologyClosedError: Topology is closed, please connect * Mongo Atlas: Connections % of configured limit has gone above 80 Connection storming occurs when your application has to mount a connection to Mongo for every serverless function or API endpoint call. Vercel executes your application’s code in a highly concurrent and isolated fashion. So, if you create new database connections on each request, your app might quickly exceed the connection limit of your database. We can leverage Vercel’s fluid compute model to keep our database connection objects warm across function invocations. Traditional serverless architecture was designed for quick, stateless web app transactions. Now, especially with the rise of LLM-oriented applications built with Next.js, interactions with applications are becoming more sequential. We just need to ensure that we assign our MongoDB connection to a global variable. Protip: Use global variables Vercel’s fluid compute model means all memory, including global constants like a MongoDB client, stays initialized between requests as long as the instance remains active. By assigning your MongoDB client to a global constant, you avoid redundant setup work and reduce the overhead of cold starts. This enables a more efficient approach to reusing connections for your application’s MongoDB client. The example below demonstrates how to retrieve an array of users from the users collection in MongoDB and either return them through an API request to /api/users or render them as an HTML list at the /users route. To support this, we initialize a global clientPromise variable that maintains the MongoDB connection across warm serverless executions, avoiding re-initialization on every request. ` Using this database connection in your API route code is easy: ` You can also use this database connection in your server-side rendered React components. ` In serverless environments like Vercel, managing database connections efficiently is key to avoiding connection storming. By reusing global variables and understanding the serverless execution model, you can ensure your Next.js app remains stable and performant....

Making sense of Multiple v-model Bindings in Vue 3 cover image

Making sense of Multiple v-model Bindings in Vue 3

This article is one of a series of articles on what’s new in Vue 3. If you haven’t checked that series yet, you can do so by visiting the links below: - Take your App to the Next Level with Vue 3 - Async Components in Vue 3 - Teleporting in Vue 3 - Your first Vue 3 app using TypeScript - Vue 3 Composition API, do you really need it? In this installment, I will introduce the new v-model in Vue 3 and go through a new feature that allows you to use multiple v-model on the same component! By design, the v-model directive allows us to bind an input value to the state of an app. We use it to create a two-way data binding on the form input, textarea, and select elements. It handles updates in two opposite directions: When the input value changes, it reflects the value onto the state inside the Component. When the Component state changes, it reflects the changes onto the form input elements. The core concept of v-model remains the same in Vue 3 with more enhancements and features. Let’s dig in! Vue 2: v-model Vue 2 supports a single v-model on any given Component. In Vue 2, to build a complex Component that supports two-way data binding, it utilizes a single v-model with one full-blown payload. The Component handles the state internally for all the input elements. It generates a single payload object representing the state of the Component. Finally, it emits an event to the parent Component with the payload attached. This method had several pitfalls, especially for creating Vue UI Libraries. Of these pitfalls is the vagueness of the payload interface. It’s unclear what’s being included in the payload. A developer had to loop through the payload object in order to uncover what properties were there. Another is the need to write the logic inside the Component to handle the internal state and the generation of the payload object. Shortly, we will uncover what has been improved in this regard with Vue 3. However, before this, let’s review some basics on how Vue 2 handles implementing two-way data binding in Components. Vue 2: Two-way Data Binding As mentioned, Vue 2 uses the v-model directive to support two-way data binding on Components. Internally, it follows certain steps and rules in order to support the v-model directive. By default, the v-model directive uses different properties and emits different events for different input elements: Text and Textarea elements use the value property and the input event Checkboxes and Radio buttons use the checked property and the change event Select fields use the input property and the change event. Building a Component with a single input element will internally use something similar to the snippet below: ` The custom Component above defines a single prop named value as follows: ` Then, in the parent Component, you use the new custom Component as follows: ` The v-model directive assumes that the CustomComponent defines an internal property named value and emits a single event named input. What if the CustomComponent has to handle multiple inputs? How do we accomplish that in Vue 2? Well, there is no official solution. However, there are two methods that you can use: The CustomComponent defines a single property named value of type Object. Internally, it parses the object into data fields and does the mapping manually on the template. On every change of any of the fields, it prepares a payload for all the fields and emits a single input event, and attaches the payload. That’s a lot of code to write for such a custom component. The other option is to skip using the v-model directive and instead utilize individual input/event pairs. I will illustrate this in a moment. Assuming you have a custom Component to handle the user’s first name and last name, you would employ something similar: ` As for the properties, the Component defines the following: ` Finally, the parent Component uses the new component as follows: ` We are not using the v-model anymore and providing multiple two-way data bindings on the new component. Further your understanding by reading the official docs on Using v-model on Components Vue 3: v-model In Vue 3, the v-model directive has had an overhaul to give developers more power and flexibility when building custom components that support two-way data binding. The v-model directive now supports new defaults. The default v-model property is renamed to modelValue instead of the old name of value. The default v-model event is renamed to update:modelValue instead of the old name of input. You might be thinking that's more typing when using the new v-model directive. The Vue team are one step ahead and have given you a shorthand to use instead. Let’s rebuild the custom component using it. ` The custom component defines a single prop named modelValue as follows: ` Then, in the parent component, use the new custom component as follows: ` The new v-model directive offers the new shorthand that is used like this: ` The v-model directive assumes that the CustomComponent defines an internal property named modelValue and emits a single event named update:ModelValue. In case you don’t want to use the default naming convention, feel free to use another name. Just remember to be consistent when naming properties. Here’s an example of using a custom name for the modelValue property. ` The custom component above defines a single prop named modelValue as follows: ` Then, in the parent component, you use the new custom component like so: ` Notice the use of the property fullName instead of the default property name. Vue 3: Multiple v-model directive bindings I hope the Vue 3 shorthand form of the v-model directive has given you a "hand up". With this, the v-model gives the flexibility to use multiple v-model directives on a single component instance. The modelValue can be renamed to whatever you want, allowing you to do this! This great new feature eliminates the previous two solutions I offered up on handling complex custom components for Vue 2. Let's jump in and go through an example demonstration! Demo - Multiple v-model directive bindings Let’s build a custom Address component that can be embedded in any form to collect a user’s address. > You can play with the example live on: vue3-multiple-v-model. > You can check the source code for the example on: vue3-multiple-v-model. Figure 1 below shows the final app in action. Let’s start by building the HTML template of the new component. Figure 1 shows that all the fields used are of type input elements. Except for the last one which is a checkbox element. Therefore, it’s suffice to focus on a single input field that will eventually be replicated for the rest of fields. ` The address-line input field binds the :value directive and the @input event as per the new v-model directive specifications in Vue 3. The component defines the following property: ` The other fields follow the same structure and naming convention. Let’s look at the checkbox field and see how it’s defined: ` In the case of a checkbox field element, we bind to the :checked directive instead of the :value directive. Also, we use the @change event instead of the @input event as in the case of input field elements. The event name follows the same standard way of emitting events in the new v-model directive. The component defines the following property: ` Let’s now embed the new custom Address component into the App component: ` For each and every property on the custom component, we bind using the v-model:{property-name} format. The modelValue was replaced with the specific property names we have in hand. When there was a single input binding, the shorthand format was so much easier. However, when there are multiple input elements, the modelValue is in a league of its own! Now, let’s define the properties inside the App component using the new Composition API setup() function: ` You create a new reactive property with an object payload. Finally, you return the reactive property to the component and use it to set bindings on the custom Address component as follows: ` That’s it! Conclusion Vue 3 has many new features and improvements. Today, we saw how we use multiple v-model directives on a single component instance. There is so much more to learn and uncover in Vue 3. The coming installments of this series will continue to look at different features to help you move from Vue 2 to Vue 3. Happy Vueing!...

Vercel BotID: The Invisible Bot Protection You Needed cover image

Vercel BotID: The Invisible Bot Protection You Needed

Nowadays, bots do not act like “bots”. They can execute JavaScript, solve CAPTCHAs, and navigate as real users. Traditional defenses often fail to meet expectations or frustrate genuine users. That’s why Vercel created BotID, an invisible CAPTCHA that has real-time protections against sophisticated bots that help you protect your critical endpoints. In this blog post, we will explore why you should care about this new tool, how to set it up, its use cases, and some key considerations to take into account. We will be using Next.js for our examples, but please note that this tool is not tied to this framework alone; the only requirement is that your app is deployed and running on Vercel. Why Should You Care? Think about these scenarios: - Checkout flows are overwhelmed by scalpers - Signup forms inundated with fake registrations - API endpoints draining resources with malicious requests They all impact you and your users in a negative way. For example, when bots flood your checkout page, real customers are unable to complete their purchases, resulting in your business losing money and damaging customer trust. Fake signups clutter the app, slowing things down and making user data unreliable. When someone deliberately overloads your app’s API, it can crash or become unusable, making users angry and creating a significant issue for you, the owner. BotID automatically detects and filters bots attempting to perform any of the above actions without interfering with real users. How does it work? A lightweight first-party script quickly gathers a high set of browser & environment signals (this takes ~30ms, really fast so no worry about performance issues), packages them into an opaque token, and sends that token with protected requests via the rewritten challenge/proxy path + header; Vercel’s edge scores it, attaches a verdict, and checkBotId() function simply reads that verdict so your code can allow or block. We will see how this is implemented in a second! But first, let’s get started. Getting Started in Minutes 1. Install the SDK: ` 1. Configure redirects Wrap your next.config.ts with BotID’s helper. This sets up the right rewrites so BotID can do its job (and not get blocked by ad blockers, extensions, etc.): ` 2. Integrate the client on public-facing pages (where BotID runs checks): Declare which routes are protected so BotID can attach special headers when a real user triggers those routes. We need to create instrumentation-client.ts (place it in the root of your application or inside a src folder) and initialize BotID once: ` instrumentation-client.ts runs before the app hydrates, so it’s a perfect place for a global setup! If we have an inferior Next.js version than 15.3, then we would need to use a different approach. We need to render the React component inside the pages or layouts you want to protect, specifying the protected routes: ` 3. Verify requests on your server or API: ` - NOTE: checkBotId() will fail if the route wasn’t listed on the client, because the client is what attaches the special headers that let the edge classify the request! You’re all set - your routes are now protected! In development, checkBotId() function will always return isBot = false so you can build without friction. To disable this, you can override the options for development: ` What happens on a failed check? In our example above, if the check failed, we return a 403, but it is mostly up to you what to do in this case; the most common approaches for this scenario are: - Hard block with a 403 for obviously automated traffic (just what we did in the example above) - Soft fail (generic error/“try again”) when you want to be cautious. - Step-up (require login, email verification, or other business logic). Remember, although rare, false positives can occur, so it’s up to you to determine how you want to balance your fail strategy between security, UX, telemetry, and attacker behavior. checkBotId() So far, we have seen how to use the property isBot from checkBotId(), but there are a few more properties that you can leverage from it. There are: isHuman (boolean): true when BotID classifies the request as a real human session (i.e., a clear “pass”). BotID is designed to return an unambiguous yes/no, so you can gate actions easily. isBot (boolean): We already saw this one. It will be true when the request is classified as automated traffic. isVerifiedBot (boolean): Here comes a less obvious property. Vercel maintains and continuously updates a comprehensive directory of known legitimate bots from across the internet. This directory is regularly updated to include new legitimate services as they emerge. This could be helpful for allowlists or custom logic per bot. We will see an example in a sec. verifiedBotName? (string): The name for the specific verified bot (e.g., “claude-user”). verifiedBotCategory? (string): The type of the verified bot (e.g., “webhook”, “advertising”, “ai_assistant”). bypassed (boolean): it is true if the request skipped BotID check due to a configured Firewall bypass (custom or system). You could use this flag to avoid taking bot-based actions when you’ve explicitly bypassed protection. Handling Verified Bots - NOTE: Handling verified bots is available in botid@1.5.0 and above. It might be the case that you don’t want to block some verified bots because they are not causing damage to you or your users, as it can sometimes be the case for AI-related bots that fetch your site to give information to a user. We can use the properties related to verified bots from checkBotId() to handle these scenarios: ` Choosing your BotID mode When leveraging BotID, you can choose between 2 modes: - Basic Mode: Instant session-based protection, available for all Vercel plans. - Deep Analysis Mode: Enhanced Kasada-powered detection, only available for Pro and Enterprise plan users. Using this mode, you will leverage a more advanced detection and will block the hardest to catch bots To specify the mode you want, you must do so in both the client and the server. This is important because if either of the two does not match, the verification will fail! ` Conclusion Stop chasing bots - let BotID handle them for you! Bots are and will get smarter and more sophisticated. BotID gives you a simple way to push back without slowing your customers down. It is simple to install, customize, and use. Stronger protection equals fewer headaches. Add BotID, ship with confidence, and let the bots trample into a wall without knowing what’s going on....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co