Skip to content

Functional Programming in TypeScript using the fp-ts library: Pipe and Flow Operator

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.

Functional programming (FP) is an approach to software development that uses pure functions to help developers in trying to create maintainable and easy-to-test software. FP is notable for its ability to efficiently parallelize pure functions. This approach should lead to code that is easier to reason about and test, and can often result in more concise and maintainable code.

What you will find in this post

Reading about “pure functions” or “parallelizing” things could be scary. Everything seems very “mathematical” and “theoretical”, but don’t be afraid: the goal of this post is to try to explain in a really practical way (theory and math will pop out only when really necessary) how to bring these core concepts and approach of FP in your TS project using Giulio Canti’s library fp-ts.

Pure and Impure functions

Pure functions always produce the same output for the same input, regardless of the context in which it is called.

Calling this type of function also has no side effects, meaning it does not modify any external state or interact with the outside world in any way. Here is an example of such pure function:

function doubleNumbers(numbers: number[]): number[] {
	return numbers.map((n) => n * 2);
}

This function takes an array of numbers, doubles each number in the array, and returns a new array with the doubled numbers. Here are some characteristics of this function that make it pure:

  1. No side effects: This function doesn't modify any external state outside of its own scope. It only operates on the input array, and returns a new array with the transformed values.

  2. Deterministic: Given the same input, this function will always return the same output. There are no random or unpredictable behaviors.

  3. No dependencies: This function doesn't rely on any external state or dependencies. It only depends on the input that's passed to it.

Because of these characteristics, this function is considered pure. It's predictable, testable, and doesn't introduce any unexpected behavior.

A side effect occurs in a program when you insert external code into your function. This prevents the function from “purely” performing its task.

An impure function in TypeScript is a function that, when called with the same arguments, may produce different results each time it is called. This is because an impure function can depend on mutable state or external factors, such as the current time, user input, or global variables, which can change between calls.

Here's an example of an impure function in TypeScript:

let counter = 0;

function incrementCounter(value: number): number {
	counter += value;
	return counter;		
}

In this example, the incrementCounter function modifies the global counter variable every time it is called. Since the function's return value depends on the current value of counter, calling the function with the same argument multiple times may produce different results.

For example, if we call the function like this:

incrementCounter(1); // returns 1

incrementCounter(1); // returns 2

incrementCounter(1); // returns 3  

The function's return value changes each time we call it because the value of counter is being modified by each call. This makes incrementCounter an impure function.

Note that impure functions can make it harder to reason about code since their behavior can be unpredictable. In general, it's best to minimize the use of impure functions and rely on pure functions, which have no side effects and always produce the same output for a given input.

Actions, Calculations, and Data - Thinking like a functional programmer

Let’s try to focus one moment on side effects.

The definition says FP avoids side effects, but side effects are the very reason we run our software. The definition seems to imply that we must try to completely avoid them when in reality, we use side effects when we have to. Functional programmers know side effects are necessary yet problematic, so they have a lot of tools for working with them.

A functional programmer first tries to classify the code into 3 general categories:

  • Actions

  • Calculations

  • Data

Actions depends on when they are called or how many times they are called.

Calculations and Data instead doesn’t depend on when or how many times they are called, the difference is only that calculations can be executed, data cannot; you don’t really know what calculation will do until you run it.

Functional programmers prefer data to calculations and calculations to actions and they try to build code by applying and composing as many “calculations” as possible in order to work with "solid" data (but also trying to “control” actions too).

Fp-Ts

There are many famous functional programming languages such as Haskell, Scala, Elm, Erlang, Elixir etc.

Fp-Ts provides developers with popular patterns and reliable abstractions from typed functional languages in TypeScript.

In this post, we will focus on the first two building blocks of fp-ts: Pipe and Flow operators.

Pipe Operator

The pipe operator is a built-in function in fp-ts that allows you to compose functions from left to right. It takes a value as its first argument and any number of functions as subsequent arguments (that accept only one argument of the same type of the returning type of the preceding function). The output of each function becomes the input of the next function in the pipeline, and the final result is returned.

import { pipe } from 'fp-ts/function';

const result = pipe(
	1,
	increment,
	double,
	decrement
);

function increment(n: number): number {
	return n + 1;
}  

function double(n: number): number {
	return n * 2;
}

function decrement(n: number): number {
	return n - 1;
}

In this example, we start with the number. Then increment it, double it, and finally decrement it. The pipe operator allows us to chain these functions together in a readable and concise way.

Why use the pipe operator?

The pipe operator is useful for a few reasons:

  1. It makes code more readable. By chaining functions together with the pipe operator, it is easy to see the flow of data through the functions.

  2. It makes code more concise. Without the pipe operator, we would have to nest function calls, which can be hard to read and understand.

  3. It makes code more modular. By breaking down a problem into smaller, composable functions, we can write more reusable code.

Flow Operator

We could say that the pipe operator is our basic brick to build our ecosystem, flow is really similar but it allows you to define a sequence of functions separately and then apply them to a value later.

The flow operator is also a built-in function in fp-ts, it takes any number of functions as arguments and returns a new function that applies each function in order.

import { flow } from 'fp-ts/function';

const addOne = (x: number) => x + 1;

const double = (x: number) => x * 2;

const addOneAndDouble = flow(addOne, double);

console.log(addOneAndDouble(2)); // Output: 6

In the example above, we create two simple functions addOne and double that takes a number and return a number. We then use the flow function from fp-ts to compose the two functions. The flow function takes any number of functions as arguments and returns a new function that applies each function in sequence from left to right.

By using the Flow operator, we don't need to explicitly define the type of the addOne and double functions' parameters. TypeScript can infer their types based on how they are used in the function composition. This makes the code shorter and more readable while still ensuring type safety.

Pros of using the Flow operator in fp-ts:

  1. Type inference: The Flow operator allows TypeScript to infer the types of function parameters, making the code shorter and more readable while still ensuring type safety.

  2. Composability: The Flow function provided by fp-ts makes it easy to compose multiple functions into a single function.

Cons of using the Flow operator in fp-ts:

  1. Learning curve: If you are new to functional programming, the Flow operator can be challenging to understand and use correctly.

  2. Debugging: Since the Flow operator relies on type inference, it can be challenging to debug issues related to type mismatches or incorrect function composition.

Differences between pipe and flow

The key difference between pipe and flow is in how they handle type inference. Pipe is better at inferring types, as it can use the output type of one function as the input type of the next function in the pipeline. Flow, on the other hand, requires explicit type annotations to be added to the composed functions.

When to use Pipe or Flow

Both pipe and flow are useful tools for composing functions and creating pipelines in a functional and declarative way. However, there are some situations where one might be more appropriate than the other.

Pipe is a good choice when you need to perform a linear sequence of transformations on a value in left-to-right order.

Flow is a good choice when you need to create a reusable function that encapsulates a series of transformations.

Conclusion

Fp-ts is a powerful library that provides many tools and abstractions for functional programming in TypeScript. The pipe and flow operators are just two of the many features that it offers. In this post we started to explore the building blocks of this library, learning their powers and their main differences. If you're interested in learning more about functional programming, explore some of these other concepts and check out the fp-ts documentation for more information, or wait for the next blog post here on This Dot Blog!

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

How to configure and optimize a new Serverless Framework project with TypeScript cover image

How to configure and optimize a new Serverless Framework project with TypeScript

How to configure and optimize a new Serverless Framework project with TypeScript If you’re trying to ship some serverless functions to the cloud quickly, Serverless Framework is a great way to deploy to AWS Lambda quickly. It allows you to deploy APIs, schedule tasks, build workflows, and process cloud events through a code configuration. Serverless Framework supports all the same language runtimes as Lambda, so you can use JavaScript, Ruby, Python, PHP, PowerShell, C#, and Go. When writing JavaScript though, TypeScript has emerged as a popular choice as it is a superset of the language and provides static typing, which many developers have found invaluable. In this post, we will set up a new Serverless Framework project that uses TypeScript and some of the optimizations I recommend for collaborating with teams. These will be my preferences, but I’ll mention other great alternatives that exist as well. Starting a New Project The first thing we’ll want to ensure is that we have the serverless framework installed locally so we can utilize its commands. You can install this using npm: ` From here, we can initialize the project our project by running the serverless command to run the CLI. You should see a prompt like the following: We’ll just use the Node.js - Starter for this demo since we’ll be doing a lot of our customization, but you should check out the other options. At this point, give your project a name. If you use the Serverless Dashboard, select the org you want to use or skip it. For this, we’ll skip this step as we won’t be using the dashboard. We’ll also skip deployment, but you can run this step using your default AWS profile. You’ll now have an initialized project with 4 files: .gitignore index.js - this holds our handler that is configured in the configuration README.md - this has some useful framework commands that you may find useful serverless.yml - this is the main configuration file for defining your serverless infrastructure We’ll cover these in more depth in a minute, but this setup lacks many things. First, I can’t write TypeScript files. I also don’t have a way to run and test things locally. Let’s solve these. Enabling TypeScript and Local Dev Serverless Framework’s most significant feature is its rich plugin library. There are 2 packages I install on any project I’m working on: - serverless-offline - serverless-esbuild Serverless Offline emulates AWS features so you can test your API functions locally. There aren’t any alternatives to this for Serverless Framework, and it doesn’t handle everything AWS can do. For instance, authorizer functions don’t work locally, so offline development may not be on the table for you if this is a must-have feature. There are some other limitations, and I’d consult their issues and READMEs for a thorough understanding, but I’ve found this to be excellent for 99% of projects I’ve done with the framework. Serverless Esbuild allows you to use TypeScript and gives you extremely fast bundler and minifier capabilities. There are a few alternatives for TypeScript, but I don’t like them for a few reasons. First is Serverless Bundle, which will give you a fully configured webpack-based project with other features like linters, loaders, and other features pre-configured. I’ve had to escape their default settings on several occasions and found the plugin not to be as flexible as I wanted. If you need that advanced configuration but want to stay on webpack, Serverless Webpack allows you to take all of what Bundle does and extend it with your customizations. If I’m getting to this level, though, I just want a zero-configuration option which esbuild can be, so I opt for it instead. Its performance is also incredible when it comes to bundle times. If you want just TypeScript, though, many people use serverless-plugin-typescript, but it doesn’t support all TypeScript features out of the box and can be hard to configure. To configure my preferred setup, do the following: 1. Install the plugins by setting up your package.json. I’m using yarn but you can use your preferred package manager. ` Note: I’m also installing serverless here, so I have a local copy that can be used in package.json scripts. I strongly recommend doing this. 2. In our serverless.yml, let’s install the plugins and configure them. When done, our configuration should look like this: ` 3. Now, in our newly created package.json, let’s add a script to run the local dev server. Our package.json should now look like this: ` We can now run yarn dev in our project root and get a running server 🎉 But our handler is still in JavaScript. We’ll want to pull in some types and set our tsconfig.json to fix this. For the types, I use aws-lambda and @types/serverless, which can be installed as dev dependencies. For reference, my tsconfig.json looks like this: ` And I’ve updated our index.js to index.ts and updated it to read as follows: ` With this, we now have TypeScript running and can do local development. Our function doesn’t expose an HTTP route making it harder to test so let’s expose it quickly with some configuration: ` So now we can point our browser to http://localhost:3000/healthcheck and see an output showing our endpoint working! Making the Configuration DX Better ion DX Better Many developers don’t love YAML because of its strict whitespace rules. Serverless Framework supports JavaScript or JSON configurations out of the box, but we want to know if our configuration is valid as we’re writing it. Luckily, we can now use TypeScript to generate a type-safe configuration file! We’ll need to add 2 more packages to make this work to our dev dependencies: ` Now, we can change our serverless.yml to serverless.ts and rewrite it with type safety! ` Note that we can’t use the export keyword for our configuration and need to use module.exports instead. Further Optimization There are a few more settings I like to enable in serverless projects that I want to share with you. AWS Profile In the provider section of our configuration, we can set a profile field. This will relate to the AWS configured profile we want to use for this project. I recommend this path if you’re working on multiple projects to avoid deploying to the wrong AWS target. You can run aws configure –profile to set this up. The profile name specified should match what you put in your Serverless Configuration. Individual Packaging Cold starts#:~:text=Cold%20start%20in%20computing%20refers,cache%20or%20starting%20up%20subsystems.) are a big problem in serverless computing. We need to optimize to make them as small as possible and one of the best ways is to make our lambda functions as small as possible. By default, serverless framework bundles all functions configured into a single executable that gets uploaded to lambda, but you can actually change that setting by specifying you want each function bundled individually. This is a top-level setting in your serverless configuration and will help reduce your function bundle sizes leading to better performance on cold starts. ` Memory & Timeout Lambda charges you based on an intersection of memory usage and function runtime. They have some limits to what you can set these values to but out of the box, the values are 128MB of memory and 3s for timeout. Depending on what you’re doing, you’ll want to adjust these settings. API Gateway has a timeout window of 30s so you won’t be able to exceed that timeout window for HTTP events, but other Lambdas have a 15-minute timeout window on AWS. For memory, you’ll be able to go all the way to 10GB for your functions as needed. I tend to default to 512MB of memory and a 10s timeout window but make sure you base your values on real-world runtime values from your monitoring. Monitoring Speaking of monitoring, by default, your logs will go to Cloudwatch but AWS X-Ray is off by default. You can enable this using the tracing configuration and setting the services you want to trace to true for quick debugging. You can see all these settings in my serverless configuration in the code published to our demo repo: https://github.com/thisdot/blog-demos/tree/main/serverless-setup-demo Other Notes Two other important serverless features I want to share aren’t as common in small apps, but if you’re trying to build larger applications, this is important. First is the useDotenv feature which I talk more about in this blog post. Many people still use the serverless-dotenv-plugin which is no longer needed for newer projects with basic needs. The second is if you’re using multiple cloud services. By default, your lambdas may not have permission to access the other resources it needs. You can read more about this in the official serverless documentation about IAM permissions. Conclusion If you’re interested in a new serverless project, these settings should help you get up and running quickly to make your project a great developer experience for you and those working with you. If you want to avoid doing these steps yourself, check out our starter.dev serverless kit to help you get started....

TypeScript Integration with .env Variables cover image

TypeScript Integration with .env Variables

Introduction In TypeScript projects, effectively managing environment variables can significantly enhance the development experience. However, a common hurdle is that TypeScript, by default, doesn't recognize variables defined in .env files. This oversight can lead to type safety issues and, potentially, hard-to-trace bugs. In this blog post, we'll walk you through the process of setting up an environment.d.ts file. This simple yet powerful addition enables TypeScript to seamlessly integrate with and accurately interpret your environment variables. Let's dive into the details! Creating and Configuring environment.d.ts Install @types/node Before creating your environment.d.ts file, make sure you have the @types/node package installed as it provides TypeScript definitions for Node.js, including the process.env object. Install it as a development dependency: ` Setting Up environment.d.ts To ensure TypeScript correctly recognizes and types your .env variables, start by setting up an environment.d.ts file in your project. This TypeScript declaration file will explicitly define the types of your environment variables. 1. Create the File: In the root of your TypeScript project, create a file named environment.d.ts 2. Declare Environment Variables: In environment.d.ts, declare your environment variables as part of the NodeJS.ProcessEnv interface. For example, for API_KEY and DATABASE_URL, the file would look like this: ` 3. Typescript config: In you tsconfig.json file, ensure that Typescript will recognize our the new file: ` 4. Usage in Your Project: With these declarations, TypeScript will provide type-checking and intellisense for process.env.API_KEY and process.env.DATABASE_URL, enhancing the development experience and code safety. Checking on Your IDE By following the steps above, you can now verify on your IDE how your environment variables recognizes and auto completes the variables added: Conclusion Integrating .env environment variables into TypeScript projects enhances not only the security and flexibility of your application but also the overall developer experience. By setting up an environment.d.ts file and ensuring the presence of @types/node, you bridge the gap between TypeScript’s static type system and the dynamic nature of environment variables. This approach leads to clearer, more maintainable code, where the risks of runtime errors are significantly reduced. It's a testament to TypeScript's versatility and its capability to adapt to various development needs. As you continue to build and scale your TypeScript applications, remember that small enhancements like these can have a profound impact on your project's robustness and the efficiency of your development processes. Embrace these nuanced techniques, and watch as they bring a new level of precision and reliability to your TypeScript projects....

Awesome 3D experience with VueJS and TresJS: a beginner's guide cover image

Awesome 3D experience with VueJS and TresJS: a beginner's guide

Awesome 3D experience with VueJS and TresJS: a beginner's guide Vue.js developers are renowned for raving about the ease, flexibility, and speed of development their framework offers. Tres.js builds on this love for Vue by becoming the missing piece for seamless 3D integration. As a Vue layer for Three.js, Tres.js allows you to leverage the power of Three.js, a popular 3D library, within the familiar and beloved world of Vue components. This means you can create stunning 3D graphics and animations directly within your Vue applications, all while maintaining the clean and efficient workflow you've come to expect. TresJS is a library specifically designed to make incorporating WebGL (the web's 3D graphics API) into your Vue.js projects a breeze. It boasts several key features that make 3D development with Vue a joy: - Declarative Approach: Build your 3D scenes like you would any other Vue component, leveraging the power and familiarity of Vue's syntax. This makes it intuitive and easy to reason about your 3D elements. - Powered by Vite: Experience blazing-fast development cycles with Vite's Hot Module Replacement (HMR) that keeps your scenes updated in real-time, even as your code changes. - Up-to-date Features: Tres.js stays on top of the latest Three.js releases, ensuring you have immediate access to the newest features and functionality. - Thriving Ecosystem: The Tres.js ecosystem offers many resources to enhance your development experience. This includes: - Cientos: A collection of pre-built components and helpers that extend the capabilities of Tres.js, allowing you to focus on building your scene's functionality rather than reinventing the wheel (https://cientos.tresjs.org/). - TresLeches: A powerful state management solution specifically designed for 3D applications built with Tres.js (https://tresleches.tresjs.org/). You can try TresJS online using their official Playground or on their StackBlitz starter. But now, let's dive into a quick code example to showcase the simplicity of creating a 3D scene with TresJS. Setup First, install the package: npm install @tresjs/core three And then, if you are using Typescript, be sure to install the types: npm install @types/three -D If you are using Vite, now you need to modify your vite.config.ts file in this way to make the template compiler work with the custom renderer: ` Create our Scene Imagine a 3D scene as a virtual stage. To bring this stage to life, we need a few key players working together: 1. Scene: Think of this as the container that holds everything in your 3D world. It acts as the canvas where all the objects, lights, and the camera reside, defining the overall environment. 2. Renderer: This is the magician behind the curtain, responsible for taking all the elements in your scene and translating them into what you see on the screen. It performs the complex calculations needed to transform your 3D scene into 2D pixels displayed on your browser. 3. Camera: Like a real camera, this virtual camera defines the perspective from which you view your scene. You can position and adjust the camera to zoom in, zoom out, or explore different angles within your 3D world. - To make our camera dynamic and allow canvas exploration, we are going to leverage the client's OrbitControls component. Below are our examples. You will see that we just include the component in our canvas, and it just works. 4. Objects: These actors bring your scene to life. They can be anything from simple geometric shapes like spheres and cubes to complex models like characters or buildings. You create the visual elements that tell your story by manipulating and animating these objects. Starting from the beginning: to create our Scene with TresJS we just need to use our component TresCanvas in our Vue component's template: ` The TresCanvas component is going to do some setup work behind the scenes: - It creates a WebGLRenderer that automatically updates every frame. - It sets the render loop to be called on every frame based on the browser refresh rate. Using the window-size property, we force the canvas to take the width and height of our full window. So with TresCanvas component we have created our Renderer and our Scene. Let's move to the Camera: ` We just have to add the TresPerspectiveCamera component to our scene. NOTE: It's important that all scene-related components live between the TresCanvas component. Now, only the main actor is missing, let's add some styles and our object inside the scene. Our Vue component will now look like: ` And our scene will be: A Mesh is a basic scene object in three.js, and it's used to hold the geometry and the material needed to represent a shape in 3D space. As we can see, we can achieve the same with TresJS using the TresMesh component, and between the default slots, we are just passing our object (a Box in our example). One interesting thing to notice is that we don't need to import anything. That's because TresJS automatically generates a Vue Component based on the three objects you want to use in PascalCase with a Tres prefix. Now, if we want to add some color to our object the Three.js Material class comes to help us. We need to add: ` Conclusion Tres.js not only supercharges Vue.js applications with stunning 3D graphics, but it also integrates seamlessly with Nuxt.js, enabling you to harness the performance benefits of server-side rendering (SSR) for your 3D creations. This opens the door to building exceptional web experiences that are both interactive and performant. With Tres.js, Vue.js developers can leverage a declarative approach, cutting-edge features, and a vast ecosystem to bring their immersive web visions to life. If you want to elevate your Vue.js projects with a new dimension, Tres.js is an excellent choice to explore....

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