<?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: Hadil Ben Abdallah</title>
    <description>The latest articles on DEV Community by Hadil Ben Abdallah (@hadil).</description>
    <link>https://dev.to/hadil</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%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png</url>
      <title>DEV Community: Hadil Ben Abdallah</title>
      <link>https://dev.to/hadil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hadil"/>
    <language>en</language>
    <item>
      <title>OpenRouter Alternatives: 5 AI API Gateways Worth Considering in 2026</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Tue, 03 Nov 2026 13:40:51 +0000</pubDate>
      <link>https://dev.to/bearerclub/openrouter-alternatives-5-ai-api-gateways-worth-considering-in-2026-2l56</link>
      <guid>https://dev.to/bearerclub/openrouter-alternatives-5-ai-api-gateways-worth-considering-in-2026-2l56</guid>
      <description>&lt;p&gt;When an application sends requests to more than one AI model, keeping those integrations organized quickly becomes its own engineering problem.&lt;/p&gt;

&lt;p&gt;OpenRouter solves this by giving developers a single API for routing requests across hundreds of models. It is one of the most widely used options for multi-model access, and for many developers it works well enough that they never look further.&lt;/p&gt;

&lt;p&gt;The cases where it falls short are usually specific. Some teams want control over where their prompts are processed and do not want them routed through an external managed service. Others need a pricing model that is predictable at scale, rather than a per-token markup on top of provider list prices. A few need production-grade observability tools built into the gateway layer.&lt;/p&gt;

&lt;p&gt;In this article, we will compare five OpenRouter alternatives worth considering in 2026: Bearer Club, LiteLLM, Portkey, AI/ML API, and Requesty. The comparison focuses on what actually matters in a production setup: model access, pricing structure, data handling, and how much operational work each option adds.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The best OpenRouter alternative depends on whether predictable pricing, self-hosted control, or production observability is the priority.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://bearer.club" rel="noopener noreferrer"&gt;Bearer Club&lt;/a&gt;:&lt;/strong&gt; A membership-based AI API service that provides access to 60+ models through a single OpenAI-compatible key. Members pay an annual fee and access models at a discount below provider list prices. Best for indie developers and small teams who use multiple models and want one predictable bill instead of managing separate provider accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://litellm.ai" rel="noopener noreferrer"&gt;LiteLLM&lt;/a&gt;:&lt;/strong&gt; An open source Python-based gateway and proxy server that supports 100+ model providers through an OpenAI-compatible interface. Teams self-host it and retain full control over routing, configuration, and data handling. Best for engineering teams comfortable running their own infrastructure who need full control over the gateway layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://portkey.ai" rel="noopener noreferrer"&gt;Portkey&lt;/a&gt;:&lt;/strong&gt; A managed AI gateway with a strong focus on observability, tracing, and prompt management. It logs every request with latency, token usage, cost, and metadata. Best for teams that need production-grade visibility into AI requests without building that infrastructure themselves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aimlapi.com" rel="noopener noreferrer"&gt;AI/ML API&lt;/a&gt;:&lt;/strong&gt; A managed API platform with access to 200+ models on a pay-as-you-go basis. No subscription or commitment required. Best for developers who want broad model access with irregular or experimental usage patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://requesty.ai" rel="noopener noreferrer"&gt;Requesty&lt;/a&gt;:&lt;/strong&gt; A lightweight managed AI gateway focused on simplicity. It provides model access through an OpenAI-compatible endpoint with minimal configuration. Best for developers who need to switch between providers quickly without complex routing requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main divide is between self-hosted control and managed access. Within the managed options, the differences come down to pricing model, how much observability comes built in, and how broad the model catalog is.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an AI API Gateway?
&lt;/h2&gt;

&lt;p&gt;An AI API gateway is a layer that sits between an application and the AI model providers it uses.&lt;/p&gt;

&lt;p&gt;Without a gateway, an application that connects to OpenAI, Anthropic, Google, and Mistral needs a separate integration for each. Different authentication flows, different request formats, different error handling, and separate billing accounts. As the number of providers grows, that integration work becomes an ongoing maintenance task, and the logic for managing it spreads across the codebase.&lt;/p&gt;

&lt;p&gt;A gateway replaces those separate integrations with a single interface. The application sends requests to one endpoint, and the gateway handles routing, provider authentication, and response normalization. Depending on the platform and configuration, a gateway can also provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified APIs:&lt;/strong&gt; A single endpoint compatible with the OpenAI SDK, regardless of which model handles the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model routing:&lt;/strong&gt; Direct requests to specific models based on application logic or configured rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries and fallback:&lt;/strong&gt; Redirect requests when a provider returns an error or is unavailable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability:&lt;/strong&gt; Track latency, token usage, costs, and errors across providers from one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost control:&lt;/strong&gt; Apply budgets, rate limits, or usage caps across teams or applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data policy management:&lt;/strong&gt; Control where prompts are sent and how they are handled after a request completes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value of a gateway increases as the number of providers and models in active use grows. A small application using one model may not need one. A production system routing requests across multiple providers at volume has a clearer case for the abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  How We Evaluated These OpenRouter Alternatives
&lt;/h2&gt;

&lt;p&gt;This comparison looks at how each option fits into a real development environment, with attention to both its technical capabilities and its cost model.&lt;/p&gt;

&lt;p&gt;The main evaluation criteria are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model and provider access:&lt;/strong&gt; How many models are available, and how current is the catalog?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing model:&lt;/strong&gt; Per-token, subscription, membership, or usage-based? What does the effective cost look like at realistic volumes?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI compatibility:&lt;/strong&gt; Can existing code connect by changing only the base URL and API key?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data policy:&lt;/strong&gt; What happens to prompts after they are sent? Is there an option that avoids storing them for training?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational overhead:&lt;/strong&gt; How much infrastructure work does the option add?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability:&lt;/strong&gt; What visibility is available into requests, costs, and errors in production?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenRouter is included in the comparison table as the baseline. Each alternative is evaluated against what OpenRouter offers rather than against each other in isolation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Comparison: OpenRouter Alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gateway&lt;/th&gt;
&lt;th&gt;Model access&lt;/th&gt;
&lt;th&gt;Pricing model&lt;/th&gt;
&lt;th&gt;OpenAI compatible&lt;/th&gt;
&lt;th&gt;Self-hosted&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bearer Club&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;60+ models&lt;/td&gt;
&lt;td&gt;Annual membership&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;Predictable cost, multiple models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LiteLLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100+ providers&lt;/td&gt;
&lt;td&gt;Free (self-hosted)&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;Full infrastructure control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Portkey&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;250+ models&lt;/td&gt;
&lt;td&gt;Usage-based + plans&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Production observability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI/ML API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;200+ models&lt;/td&gt;
&lt;td&gt;Pay-per-token&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;Wide catalog, no commitment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Requesty&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50+ models&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;Simple setup, fast switching&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pricing figures reflect publicly available information as of October 2026 and can change. Verify current pricing on each provider's site before making a decision.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Bearer Club
&lt;/h2&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%2F5v3pievmwgl64ceni599.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%2F5v3pievmwgl64ceni599.png" alt="Screenshot of the Bearer Club official website showing the homepage with membership tiers and model catalog" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bearer Club is a membership-based AI API service that provides access to 60+ models through a single API key and an OpenAI-compatible endpoint. Instead of paying per token at provider list price, members pay an annual fee and access models at a discount below those rates.&lt;/p&gt;

&lt;p&gt;The endpoint is &lt;code&gt;https://api.bearer.club/v1&lt;/code&gt;, compatible with any tool or library that supports the OpenAI API. Model IDs use the format &lt;code&gt;provider/model-name&lt;/code&gt;, for example &lt;code&gt;anthropic/claude-sonnet-4-6&lt;/code&gt; or &lt;code&gt;openai/gpt-4o&lt;/code&gt;. The full model catalog is available at bearer.club/models.&lt;/p&gt;

&lt;p&gt;Bearer Club also separates data handling by key type. A private key stores prompts encrypted for 30 days, then deletes them. They are never used for training. A Research Share key may license prompt data to AI labs in exchange for lower pricing. The choice is made per key, not per account, and members can use both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Install the OpenAI library if you have not already, then point it at the Bearer Club endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.bearer.club/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-bearer-club-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic/claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# provider/model-name format
&lt;/span&gt;    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;Model IDs follow the format &lt;code&gt;provider/model-name&lt;/code&gt;. The full list is at bearer.club/models. Get a key at bearer.club/console/keys.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible endpoint:&lt;/strong&gt; Existing code connects by changing &lt;code&gt;base_url&lt;/code&gt; and &lt;code&gt;api_key&lt;/code&gt;. No SDK changes required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;60+ models through one key:&lt;/strong&gt; Access models from Anthropic, OpenAI, Google, Mistral, and others without managing separate accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private key option:&lt;/strong&gt; Prompts stored encrypted for 30 days, then deleted. Never used for training.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research Share option:&lt;/strong&gt; Available on any tier as an alternative key type; may license prompts to AI labs in exchange for lower effective cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annual membership pricing:&lt;/strong&gt; A flat fee instead of per-token markups, with discounts below provider list prices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7-day refund:&lt;/strong&gt; Available if the account is unused after purchase.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Guest tier is free, with a Research Share requirement and a 10,000 call per year limit. Member is $199 per year, with access to models at up to 20% below provider list prices. Executive is $1,999 per year, with discounts of up to 30% on open-weight models.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Bearer Club is best for indie developers and small AI teams who regularly use more than one model and want a single predictable bill. It is also worth considering for teams where a private key with a clear data deletion policy matters, or where the cost of managing multiple provider accounts becomes disruptive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bearer.club" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Bearer Club&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  2. LiteLLM
&lt;/h2&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%2Fui5bi276f2leuhwpc3jk.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%2Fui5bi276f2leuhwpc3jk.png" alt="Screenshot of the LiteLLM official website showing the open source gateway homepage with provider compatibility" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LiteLLM is an open source Python library and proxy server that provides a unified interface for over 100 LLM providers. It is the most widely used self-hosted option for engineering teams that need an OpenAI-compatible API across multiple model providers, and it is MIT-licensed at its core.&lt;/p&gt;

&lt;p&gt;LiteLLM translates requests sent in OpenAI format to the format expected by each provider. Applications connect to the LiteLLM proxy using the OpenAI SDK, and the proxy handles authentication, request translation, and response normalization. The gateway also includes features for routing, retries, fallbacks, usage tracking, and virtual keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and Routing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LiteLLM supports configurable routing policies for distributing requests across providers and handling provider errors. Teams can set fallback chains so that requests are redirected when a provider returns a failure. Because it runs on your own infrastructure, the overhead per request depends on how you deploy and configure it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LiteLLM includes usage tracking, virtual keys, and spend monitoring in the open source version. Teams can export logs and metrics to their existing observability systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LiteLLM is self-hosted, which means the team owns deployment, updates, monitoring, and availability. This gives full control over the configuration and where the gateway runs, but it also means taking on the operational responsibility of keeping it healthy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Your LiteLLM proxy address
&lt;/span&gt;    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-litellm-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic/claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;100+ provider support:&lt;/strong&gt; Routes requests to OpenAI, Anthropic, Google, Mistral, Cohere, Hugging Face, and dozens of other providers through a single proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible interface:&lt;/strong&gt; Applications connect using the standard OpenAI SDK. No library changes required, only the base URL and API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual keys and team spend controls:&lt;/strong&gt; Issue separate API keys per team or application, set budgets, and track usage per key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable routing and fallbacks:&lt;/strong&gt; Define fallback chains so requests are redirected automatically when a provider returns an error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MIT-licensed core:&lt;/strong&gt; The open source version is free to use, modify, and deploy without a commercial license.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Free and open source under the MIT license. A managed cloud version, LiteLLM Cloud, is available with pricing based on usage and provides a hosted option for teams that want the gateway without the infrastructure overhead.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;LiteLLM is best for engineering and platform teams that need full control over the gateway layer, want to inspect or modify how requests are routed, and are comfortable operating their own server infrastructure. It is also a strong fit for teams that need broad provider compatibility across self-hosted inference services alongside hosted APIs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://litellm.ai" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore LiteLLM&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Portkey
&lt;/h2&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%2F2wyp19di4hcj7t144zob.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%2F2wyp19di4hcj7t144zob.png" alt="Screenshot of the Portkey official website showing the AI gateway homepage with observability and prompt management features" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Portkey is a managed AI gateway with a strong focus on observability and production tooling. It provides a unified API across 250+ models alongside request tracing, prompt versioning, guardrails, and cost tracking built into the gateway layer.&lt;/p&gt;

&lt;p&gt;Portkey sits between the application and model providers, logging every request with latency, token counts, costs, and metadata. Teams can trace individual requests, compare prompt versions across experiments, set fallback chains, and apply guardrails to AI outputs. The SDK wraps the OpenAI client with minimal code changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observability and Governance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Portkey's observability layer is its main differentiator. Teams get a dashboard with request volume, latency distributions, provider error rates, and spending by model or team. Prompt management is also available in the platform, letting teams version and deploy prompts without code deploys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing and Reliability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Portkey supports fallback chains, retries, and load balancing across providers. Teams can configure routing rules and set conditions for when a request should be redirected to a different model.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;portkey_ai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Portkey&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Portkey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-portkey-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;virtual_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-virtual-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Maps to a provider key stored in Portkey
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request tracing and logging:&lt;/strong&gt; Every request is logged with latency, token counts, cost, and custom metadata for debugging and analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt versioning:&lt;/strong&gt; Manage and deploy prompts from a central dashboard without code deploys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback chains:&lt;/strong&gt; Configure automatic fallback to a secondary provider when the primary returns an error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails:&lt;/strong&gt; Apply input and output filters to AI requests at the gateway layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;250+ model support:&lt;/strong&gt; Access models from OpenAI, Anthropic, Google, Mistral, and others through a unified interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;A free tier is available. Paid plans start at $49 per month. Enterprise pricing is available for larger teams and custom deployment requirements.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Portkey is best for teams building production AI features who need visibility into what is happening across providers, want to manage prompts centrally, or need guardrails applied to AI outputs. Its value is strongest when observability and prompt management are genuine priorities rather than nice-to-haves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portkey.ai" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Portkey&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  4. AI/ML API
&lt;/h2&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%2F8d5y66hwhqi648z8wznu.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%2F8d5y66hwhqi648z8wznu.png" alt="Screenshot of the AI/ML API official website showing the managed API platform homepage with 200+ model catalog" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI/ML API is a managed API platform with access to 200+ models on a pay-as-you-go basis. It aims to provide broad model access without requiring a subscription or membership commitment, making it a practical option for teams with irregular or experimental usage.&lt;/p&gt;

&lt;p&gt;The platform provides an OpenAI-compatible endpoint. Developers add a key and change the base URL. Billing is per token, similar to accessing providers directly, but through a single account and invoice.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.aimlapi.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-aimlapi-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200+ model catalog:&lt;/strong&gt; Access models from Anthropic, OpenAI, Google, Meta, Mistral, and others through a single account and endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No subscription required:&lt;/strong&gt; Pay-per-token with no minimum commitment, making it practical for experimental or irregular usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible API:&lt;/strong&gt; Existing code connects by changing the base URL and API key with no further modifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single invoice:&lt;/strong&gt; Consolidates billing across all providers into one account rather than managing separate invoices per provider.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Pay-per-token pricing with no subscription requirement. Pricing varies by model.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;AI/ML API is best for developers who want access to a wide model catalog without committing to a subscription. A good fit when model usage is irregular, when a team is evaluating multiple models before committing to a provider, or when the range of available models matters more than cost optimization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aimlapi.com" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore AI/ML API&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  5. Requesty
&lt;/h2&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%2Fccg348v3rrkk0yh42p0g.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%2Fccg348v3rrkk0yh42p0g.png" alt="Screenshot of the Requesty official website showing the lightweight AI gateway homepage with simple provider switching" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Requesty is a lightweight managed AI gateway focused on simplicity. It provides model access through an OpenAI-compatible endpoint with a minimal configuration surface and straightforward setup.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://router.requesty.ai/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your-requesty-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic/claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&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;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-compatible endpoint:&lt;/strong&gt; Connect existing code by changing the base URL and API key with no other modifications required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-provider access:&lt;/strong&gt; Route requests to models from different providers through a single managed endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal configuration:&lt;/strong&gt; No complex routing rules or infrastructure setup required to get started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast provider switching:&lt;/strong&gt; Change the target model or provider without redeploying application code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Usage-based pricing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Requesty is best for developers who want to switch between providers quickly without a heavy setup or a large configuration surface. A good starting point for projects at an early stage where routing complexity and observability tooling are not yet priorities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://requesty.ai" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Requesty&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  How to Choose the Right OpenRouter Alternative
&lt;/h2&gt;

&lt;p&gt;Choosing an alternative to OpenRouter comes down to what your application needs today and what your team expects to manage as it grows. A gateway with a broad feature set may be unnecessary for a small project, while a basic managed proxy can become limiting when multiple services, providers, and engineering teams depend on it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which model providers do I actually need?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check whether the gateway supports the specific models your application uses. An OpenAI-compatible API simplifies integration, but compatibility does not guarantee that every provider-specific feature behaves identically. Verify the model catalog before committing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Is a managed service or self-hosted gateway the right fit?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A managed gateway runs on the provider's infrastructure. Setup is faster and there is no server to operate, but the provider handles the data routing. A self-hosted gateway runs on your own infrastructure. That gives full control over configuration and data handling, but your team takes on the operational responsibility of keeping it running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What does the pricing model look like at my volume?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Per-token pricing with a markup can become expensive at consistent volume. A flat membership or subscription fee may cost less at scale but can be wasteful for irregular usage. Model the expected cost under each pricing structure before making a decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Do I need observability built in?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teams that need to track latency, token usage, costs, and errors across providers in production will want a gateway that includes those tools. Building that layer yourself from scratch adds engineering time that a purpose-built solution can save.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What is my data policy requirement?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If prompt content is sensitive, verify what happens to requests after they are sent. Check whether there is a private key option, how long data is retained, and whether prompts are used for training. These details vary significantly between providers.&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  Can I use my existing OpenAI SDK code with these alternatives?
  &lt;br&gt;
All five options in this list provide OpenAI-compatible APIs. Existing code using the OpenAI SDK can connect by changing the &lt;code&gt;base_url&lt;/code&gt; and &lt;code&gt;api_key&lt;/code&gt; values. No other code changes are required for basic usage. Model IDs may differ by platform, so check each provider's model list for the correct format.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What is the difference between a managed gateway and a self-hosted one?
  &lt;br&gt;
A managed gateway runs on the provider's infrastructure. Setup is faster, there is no server to maintain, and updates are handled by the provider. A self-hosted gateway runs on infrastructure you control. That gives more flexibility over configuration and data handling, but your team owns deployment, monitoring, availability, and updates.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Does the gateway I choose affect model output quality?
  &lt;br&gt;
No. The gateway routes requests to the underlying model provider. The model running the inference is the same regardless of which gateway is used. Latency may vary slightly depending on gateway architecture and geographic routing.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Is OpenRouter open source?
  &lt;br&gt;
OpenRouter is not open source. It is a managed commercial service. LiteLLM is the most widely used open source alternative in this list, with an MIT-licensed core and a large provider compatibility surface.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What should I check before switching from OpenRouter?
  &lt;br&gt;
Four things worth verifying: whether the models you actually use are in the new catalog, what the data policy is for your use case, whether the pricing model fits your usage pattern, and whether the gateway adds observability you would otherwise need to build yourself.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;


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

&lt;p&gt;OpenRouter works well for most developers who need quick access to a wide model catalog. The cases where switching makes sense are usually specific: a need for predictable flat-rate pricing, a requirement for self-hosted infrastructure, or a need for production observability built into the gateway layer.&lt;/p&gt;

&lt;p&gt;Among the options covered here, Bearer Club is worth evaluating for developers and small teams who use multiple models regularly and want a single annual bill with clear data handling policies. LiteLLM is the strongest choice for teams that need full infrastructure control and broad provider compatibility. Portkey stands out for teams where observability and prompt management are priorities.&lt;/p&gt;

&lt;p&gt;Before making a decision, verify the current model catalog, pricing, and data handling terms on each provider's site. Features and pricing in this space change frequently.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>programming</category>
    </item>
    <item>
      <title>Your Website Has a Design System. Does Your Marketing Team Have a Content System?</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Tue, 03 Nov 2026 09:51:30 +0000</pubDate>
      <link>https://dev.to/yassersoliman/your-website-has-a-design-system-does-your-marketing-team-have-a-content-system-27d1</link>
      <guid>https://dev.to/yassersoliman/your-website-has-a-design-system-does-your-marketing-team-have-a-content-system-27d1</guid>
      <description>&lt;p&gt;A marketing content system gives your team a reliable way to create, organize, update, and publish website content. Your design system may already define colors, typography, buttons, spacing, and reusable page components. But those rules don't explain who owns a landing page, how messaging stays consistent, or what happens when five people need to update different parts of the website.&lt;/p&gt;

&lt;p&gt;This gap becomes noticeable as a company grows. Marketing adds new campaigns, product teams introduce features, and the website accumulates more pages, messages, and calls to action. Everyone has access to the same design components, but content decisions still happen across scattered documents, Slack conversations, spreadsheets, and individual work habits.&lt;/p&gt;

&lt;p&gt;The result can be a website that looks consistent but communicates inconsistently. A marketing team might have all the right components and still struggle to keep messaging accurate, update pages quickly, or coordinate changes across the site.&lt;/p&gt;

&lt;p&gt;That is where a marketing content system becomes useful. It gives the people responsible for the website a shared way to manage the content that goes into those carefully designed components.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;A design system keeps the visual and interface elements of your website consistent, while a marketing content system helps your team manage the words, messaging, ownership, and publishing processes behind those pages. It defines how content is created, reviewed, reused, updated, and maintained. Together, these systems help marketing teams publish faster, keep messaging aligned, and manage website changes with fewer bottlenecks.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Design System Solves a Different Problem
&lt;/h2&gt;

&lt;p&gt;A design system gives your website a shared visual language. It defines how components should look and behave, so teams can build new pages without inventing every interface element from scratch.&lt;/p&gt;

&lt;p&gt;For example, a typical design system might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typography rules for headings, body text, and labels.&lt;/li&gt;
&lt;li&gt;Standard buttons, forms, navigation, and cards.&lt;/li&gt;
&lt;li&gt;Reusable page sections and layout patterns.&lt;/li&gt;
&lt;li&gt;Spacing, color, and accessibility guidelines.&lt;/li&gt;
&lt;li&gt;Component documentation for designers and developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Established design systems such as the &lt;a href="https://atlassian.design/" rel="noopener noreferrer"&gt;Atlassian Design System&lt;/a&gt; demonstrate how shared components, design foundations, and documentation help teams create consistent digital experiences.&lt;/p&gt;

&lt;p&gt;These standards help maintain a consistent experience across the website. A new landing page can use the same button styles, form patterns, and page layouts as the rest of the site.&lt;/p&gt;

&lt;p&gt;However, the design system doesn't automatically tell your team what those components should communicate. It won't decide which product benefit belongs in a hero section, who approves a pricing-page change, or when an outdated customer quote needs replacing.&lt;/p&gt;

&lt;p&gt;Consider a company with several product pages. Each page uses the same heading styles, card layouts, and CTA buttons. Visually, everything feels connected. Yet one page describes a feature using an old product name, another promotes a benefit that has changed, and a third uses messaging that the sales team stopped using months ago.&lt;/p&gt;

&lt;p&gt;The components are consistent. The content is not.&lt;/p&gt;

&lt;p&gt;This is an ownership and content-management problem. Solving it requires a system that covers the information inside the components, along with the people and processes responsible for keeping that information accurate.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Marketing Content System Actually Covers
&lt;/h2&gt;

&lt;p&gt;A marketing content system defines how website content is managed throughout its lifecycle. It connects content decisions with the workflows, responsibilities, and technical setup that support the website.&lt;/p&gt;

&lt;p&gt;It doesn't need to be a new platform or a complicated collection of documents. For many B2B SaaS teams, it can start with clear content standards, documented ownership, reusable content patterns, and a reliable publishing process.&lt;/p&gt;

&lt;p&gt;A practical marketing content system should cover four areas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Content structure and standards&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Define how your team writes and organizes website content. This includes product terminology, messaging guidelines, heading conventions, CTA language, tone of voice, and rules for describing features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reusable content patterns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Document recurring content structures, such as hero sections, feature descriptions, customer proof, pricing explanations, and FAQ blocks. Teams should know which patterns are available and how to use them without creating inconsistent variations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ownership and review responsibilities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make it clear who writes, reviews, approves, and maintains each type of content. Product marketing may own feature messaging, while a marketing lead approves campaign positioning. Developers may support technical implementation without becoming the default approvers of every content change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Publishing and maintenance workflows&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Establish how content moves from a draft to a live page. Include review requirements, publishing permissions, update procedures, and checks for links, forms, tracking, and page behavior.&lt;/p&gt;

&lt;p&gt;These four areas work together. Content standards help people make consistent decisions, reusable patterns reduce unnecessary work, ownership prevents approval confusion, and publishing workflows make sure approved changes reach the website safely.&lt;/p&gt;

&lt;p&gt;The goal is simple: give your marketing team a dependable way to manage website content as the company, product, and website continue to grow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Content Ownership Becomes Difficult as a Website Grows
&lt;/h2&gt;

&lt;p&gt;When a company has only a few website pages, content ownership can feel straightforward. A marketer writes the copy, someone reviews it, and a developer publishes the update if technical help is needed.&lt;/p&gt;

&lt;p&gt;That process becomes harder as the website expands. New product pages, campaign landing pages, customer stories, integration pages, and resource libraries introduce more content owners and more opportunities for conflicting information.&lt;/p&gt;

&lt;p&gt;A product marketer might update a feature description while the website team is preparing a new landing page. Sales might request a change to the messaging on a pricing page, while another team is updating the same product terminology across several pages. Without clear ownership, these changes can move forward independently and create inconsistencies.&lt;/p&gt;

&lt;p&gt;The problem isn't that too many people contribute to the website. Different teams have useful information to share. The problem is that nobody has a clear view of who is responsible for the final content and how related changes should be coordinated.&lt;/p&gt;

&lt;p&gt;A content system should establish ownership at two levels:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content ownership:&lt;/strong&gt; Who is responsible for the accuracy of the information? Product marketing may own feature descriptions, while sales or customer success can provide feedback on customer-facing language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Publishing ownership:&lt;/strong&gt; Who can approve and publish the change? A marketing lead might approve the messaging, while an authorized website editor handles publication. Technical changes that affect templates, integrations, or site functionality may still require developer review.&lt;/p&gt;

&lt;p&gt;This distinction helps teams avoid unnecessary approval delays while keeping the right people involved. Marketing can manage routine content updates within agreed permissions, and developers can focus on changes that genuinely require technical work.&lt;/p&gt;

&lt;p&gt;It also makes ongoing maintenance easier. When a product feature changes, the team knows who should review the related website content and which pages may need updating.&lt;/p&gt;




&lt;h2&gt;
  
  
  Build Reusable Content Patterns Your Team Can Actually Maintain
&lt;/h2&gt;

&lt;p&gt;A design system gives teams reusable interface components. A marketing content system should give them reusable content patterns too.&lt;/p&gt;

&lt;p&gt;Think about how often a B2B SaaS website explains the same types of information. Product pages describe features and benefits. Integration pages explain compatibility and use cases. Landing pages introduce an offer, provide supporting evidence, and guide visitors toward a CTA.&lt;/p&gt;

&lt;p&gt;If every page starts from a blank document, marketers spend time solving the same structural problems repeatedly. The result can also vary significantly across pages, even when they serve similar purposes.&lt;/p&gt;

&lt;p&gt;Reusable content patterns provide a shared starting point. They define the information a page section should communicate while leaving room for the details of each product, audience, or campaign.&lt;/p&gt;

&lt;p&gt;For example, a feature section could follow a consistent structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature name:&lt;/strong&gt; What the capability is called.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer problem:&lt;/strong&gt; What difficulty it addresses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical benefit:&lt;/strong&gt; How it helps the customer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supporting evidence:&lt;/strong&gt; A product detail, example, or customer result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next step:&lt;/strong&gt; The action visitors can take to learn more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure helps writers produce complete, useful content. It also gives reviewers a consistent way to evaluate whether a section explains the feature clearly.&lt;/p&gt;

&lt;p&gt;The same principle applies to other recurring sections, including customer testimonials, integration descriptions, pricing explanations, and FAQ content.&lt;/p&gt;

&lt;p&gt;However, reusable patterns need ownership and maintenance. A template that contains outdated product terminology or an old CTA can spread the same mistake across multiple pages. Each pattern should have a clear purpose, documented usage guidance, and an owner responsible for keeping it accurate.&lt;/p&gt;

&lt;p&gt;Your website CMS may already support reusable blocks, structured content fields, or shared page templates. These capabilities can support the system, provided the team documents how and when to use them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connect Content Management to Your Website Workflow
&lt;/h2&gt;

&lt;p&gt;Even with clear standards and ownership, a content system can fail if it doesn't connect to the way website changes actually get published.&lt;/p&gt;

&lt;p&gt;A new landing page might have excellent copy and an approved design, but it still needs a publishing process. Someone must check the page structure, verify links and forms, confirm tracking, and make sure the final page works across devices.&lt;/p&gt;

&lt;p&gt;This is where content operations and WebOps meet. Content decisions need a reliable path to production, with enough checks to protect the website without making every small update a development project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Define a Clear Marketing Content System Workflow
&lt;/h3&gt;

&lt;p&gt;A practical workflow can follow five stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Request:&lt;/strong&gt; Define the page or content change, its purpose, target audience, owner, and expected outcome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Create:&lt;/strong&gt; Write or update the content using the team's messaging standards and reusable patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Review:&lt;/strong&gt; Ask the relevant stakeholders to check accuracy, positioning, terminology, and any required approvals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Publish:&lt;/strong&gt; Move the approved content to the live website through the appropriate CMS permissions and publishing process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Verify:&lt;/strong&gt; Check the published page, links, forms, analytics events, responsive layout, and other requirements affected by the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Match the Review Process to the Scope of the Change
&lt;/h3&gt;

&lt;p&gt;Not every content update needs the same level of review. Correcting a typo doesn't require the same process as changing product positioning across several landing pages. Your workflow should reflect the risk and scope of the change.&lt;/p&gt;

&lt;p&gt;For example, a simple headline correction may only need a content owner and a quick live-page check. A new pricing page may require product, marketing, and technical reviews, followed by more extensive testing.&lt;/p&gt;

&lt;p&gt;The important part is making these expectations clear before work begins. Marketing should know which updates it can publish independently, which changes require approval, and when engineering needs to get involved.&lt;/p&gt;

&lt;p&gt;This is closely connected to the wider challenge of &lt;a href="https://yassersoliman.com/blog/why-marketing-teams-cant-get-dev-to-prioritize-website-requests/" rel="noopener noreferrer"&gt;keeping marketing website requests from getting stuck in development backlogs&lt;/a&gt;. A defined content workflow helps teams submit clearer requests, handle routine updates efficiently, and give developers the context they need when technical work is necessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Keep Your Content System Accurate as the Website Evolves
&lt;/h2&gt;

&lt;p&gt;A content system needs regular maintenance. Product features change, positioning evolves, campaigns end, and customer expectations shift. Without a process for reviewing existing pages, even a well-organized website can gradually become inconsistent.&lt;/p&gt;

&lt;p&gt;This is why content maintenance should be part of normal website operations. Teams need to know which pages contain important product information, who owns them, and when they should be reviewed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build a Regular Website Content Review Process
&lt;/h3&gt;

&lt;p&gt;A few practical habits can help:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assign an owner to important pages.&lt;/strong&gt; Every key product, pricing, integration, and conversion page should have someone responsible for its accuracy. That person doesn't need to make every edit, but they should know when the content needs attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Record important content changes.&lt;/strong&gt; Keep a simple history of significant updates, including what changed, who approved it, and when it went live. This makes it easier to investigate outdated messaging or understand why a page looks different from an earlier version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review content after product changes.&lt;/strong&gt; When a feature is renamed, a pricing model changes, or a product capability is updated, identify the website pages that describe it. Product documentation and website messaging should not drift apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set review dates for high-impact pages.&lt;/strong&gt; Pricing pages, product pages, and pages used in active campaigns deserve more frequent attention than older resources that receive little traffic. A review schedule helps teams prioritize the content that matters most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remove outdated content carefully.&lt;/strong&gt; Before archiving a page or deleting an old campaign, check its traffic, backlinks, search visibility, and existing links from other pages. Some content may need an update or redirect to preserve its value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect Content Maintenance to Overall Website Health
&lt;/h3&gt;

&lt;p&gt;These practices also connect to broader website maintenance. As I explain in &lt;a href="https://yassersoliman.com/blog/hidden-cost-website-neglect/" rel="noopener noreferrer"&gt;The Hidden Cost of Website Neglect at Growing Tech Companies&lt;/a&gt;, small website issues can accumulate and affect performance, lead generation, and the experience visitors receive.&lt;/p&gt;

&lt;p&gt;The same principle applies to content. A page that hasn't been reviewed in months may still be live, indexed, and influencing a potential customer's decision. Regular ownership and review help prevent those problems from becoming part of the normal website experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Know Whether Your Marketing Content System Is Working
&lt;/h2&gt;

&lt;p&gt;A content system should make website management easier to measure. If the team introduces new guidelines and workflows but cannot tell whether they improve day-to-day work, it's difficult to know what needs adjustment.&lt;/p&gt;

&lt;p&gt;Start with a few operational measures that reflect how your team manages content.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;What it helps you understand&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time from content request to publication&lt;/td&gt;
&lt;td&gt;How efficiently updates move through the workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Number of revisions per update&lt;/td&gt;
&lt;td&gt;Whether requests and content guidelines are clear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval time&lt;/td&gt;
&lt;td&gt;Where reviews create delays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outdated pages identified&lt;/td&gt;
&lt;td&gt;Whether content maintenance is catching neglected information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publishing errors&lt;/td&gt;
&lt;td&gt;Whether quality checks are preventing mistakes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reuse of approved content patterns&lt;/td&gt;
&lt;td&gt;Whether teams are making effective use of existing structures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These metrics need context. A complex pricing-page update will naturally take longer than a small copy correction. The goal isn't to make every update follow the same timeline. It's to identify unnecessary delays, repeated work, and recurring problems.&lt;/p&gt;

&lt;p&gt;For example, if simple landing page changes consistently wait several days for technical approval, the team may need clearer publishing permissions. If reviewers repeatedly request the same messaging corrections, the content standards may need more specific examples.&lt;/p&gt;

&lt;p&gt;You can also connect operational improvements to website performance. Track relevant outcomes such as landing page conversion rates, form completion, engagement with important pages, and organic search traffic. These measures won't prove that a content system caused every improvement, but they can help show whether better content management supports the wider marketing goals.&lt;/p&gt;

&lt;p&gt;The best system is one your team can actually follow. Start with a few useful standards and responsibilities, review how they work in practice, and improve the process as the website grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  What is a marketing content system?
  &lt;br&gt;
A marketing content system is a set of standards, responsibilities, reusable patterns, and workflows that helps a team create, manage, publish, and maintain website content consistently. It gives everyone a clearer understanding of how content decisions are made and who is responsible for them.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What is the difference between a design system and a content system?
  &lt;br&gt;
A design system defines the visual and functional components of a website, including typography, colors, buttons, and layouts. A content system manages the information inside those components, including messaging, terminology, content ownership, review processes, and publishing rules. Both systems work together to create a consistent website experience.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Does a marketing content system require a new CMS?
  &lt;br&gt;
No. A new CMS isn't necessary for most teams. Your existing CMS may already support reusable blocks, structured content, editorial permissions, and publishing workflows. The first step is to establish clear standards and ownership, then identify whether your current tools support those requirements.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Who should own a company's website content?
  &lt;br&gt;
Ownership should be shared according to expertise and responsibility. Product marketing can manage product messaging, demand generation can own campaign content, and designated marketing leads can approve broader website changes. Developers should handle technical implementation and changes that affect website functionality.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  How can a content system help marketing teams publish faster?
  &lt;br&gt;
A content system reduces repeated decisions and unnecessary approval delays. Reusable content patterns give writers a starting point, clear ownership prevents confusion, and documented publishing permissions help teams handle routine updates without waiting for developers. Technical reviews remain available for changes that require engineering work.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;




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

&lt;p&gt;Your website's design system gives every page a consistent visual foundation. Your marketing content system gives the people managing those pages a consistent way to work.&lt;/p&gt;

&lt;p&gt;As a B2B SaaS website grows, content ownership, messaging, and publishing become harder to coordinate. Without clear processes, even a well-designed website can accumulate outdated information, inconsistent product descriptions, and unnecessary publishing delays.&lt;/p&gt;

&lt;p&gt;You don't need a complicated platform to address this. Start by documenting your content standards, assigning owners to important pages, creating reusable content patterns, and defining how updates move from request to publication.&lt;/p&gt;

&lt;p&gt;Then connect those practices to your existing website operations and review them as the business evolves.&lt;/p&gt;

&lt;p&gt;A well-managed website needs both systems. One keeps the experience consistent for visitors; the other helps your team keep that experience accurate and useful.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>marketing</category>
      <category>designsystem</category>
      <category>performance</category>
    </item>
    <item>
      <title>gp-grid: A Free, Open-Source TypeScript Data Grid for React, Vue, and Angular (No Paywalled Features)</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Mon, 02 Nov 2026 09:05:46 +0000</pubDate>
      <link>https://dev.to/hadil/gp-grid-a-free-open-source-typescript-data-grid-for-react-vue-and-angular-no-paywalled-5heb</link>
      <guid>https://dev.to/hadil/gp-grid-a-free-open-source-typescript-data-grid-for-react-vue-and-angular-no-paywalled-5heb</guid>
      <description>&lt;p&gt;An open-source data grid can look impressive with 1,000 rows and still struggle when your application needs to handle 100,000 or more. The same goes for features: you might find sorting and filtering in a free library, only to discover that row grouping, pivot tables, or other advanced capabilities require an enterprise license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gp-grid&lt;/strong&gt; takes a different approach. It is an open-source TypeScript data grid for React, Vue, and Angular, released under the Apache 2.0 license. It has zero external dependencies, supports large datasets through virtual scrolling, and includes all its features without paywalls.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore what makes a data grid useful, how gp-grid works, how to get started in your framework, and how it compares with AG Grid in features, bundle size, and published performance benchmarks.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gp-grid.io/" rel="noopener noreferrer"&gt;gp-grid&lt;/a&gt; is a free, &lt;a href="https://github.com/GioPat/gp-grid" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; TypeScript data grid for React, Vue, and Angular, licensed under Apache 2.0. It combines virtual scrolling, advanced data handling, and spreadsheet-style interactions without locking features behind a paid enterprise tier.&lt;/p&gt;

&lt;p&gt;Its core features include:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Row and column virtualization:&lt;/strong&gt; Render only the visible rows and columns, plus an overscan buffer, to keep large and wide grids responsive.&lt;br&gt;
✅ &lt;strong&gt;Sorting and filtering:&lt;/strong&gt; Support multi-column sorting and advanced filter conditions.&lt;br&gt;
✅ &lt;strong&gt;Cell selection and editing:&lt;/strong&gt; Work with selected ranges, keyboard navigation, inline editing, and a fill handle.&lt;br&gt;
✅ &lt;strong&gt;Custom rendering and styling:&lt;/strong&gt; Customize cells, headers, filters, themes, and dark mode.&lt;br&gt;
✅ &lt;strong&gt;Live and server-side data:&lt;/strong&gt; Manage streaming updates or fetch rows on demand for larger datasets.&lt;br&gt;
✅ &lt;strong&gt;Flexible layouts and analytics:&lt;/strong&gt; Reorder, resize, pin, and freeze columns, with row grouping, aggregation, and pivot tables.&lt;br&gt;
✅ &lt;strong&gt;AI coding agent support:&lt;/strong&gt; Use the official gp-grid skill to help coding agents integrate the correct APIs, framework bindings, and data-source patterns.&lt;/p&gt;

&lt;p&gt;gp-grid 1.0.0 supports both row and column virtualization, using overscan to render the visible viewport efficiently. Its published one-million-row benchmark reports &lt;strong&gt;56.2&lt;/strong&gt; average FPS during the measured scrolling test, although results depend on the workload and test environment.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is a Web Data Grid?
&lt;/h2&gt;

&lt;p&gt;A web data grid is an interactive component for displaying, sorting, filtering, selecting, and editing tabular data in a browser. Unlike a plain HTML table, a data grid can provide spreadsheet-style interactions, customizable cells, and virtual scrolling, which renders only the rows needed for the current viewport.&lt;/p&gt;

&lt;p&gt;The distinction matters when you're building an admin dashboard, CRM, analytics platform, financial application, or any interface where people work with large datasets.&lt;/p&gt;

&lt;p&gt;A standard HTML &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; gives you the basic structure for displaying rows and columns. You can add the behavior you need, but you'll have to build features such as sorting, filtering, and keyboard navigation yourself.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;headless table library&lt;/strong&gt; such as TanStack Table handles much of the table logic while leaving the markup and presentation to you. This offers considerable flexibility, although your team remains responsible for building the interface.&lt;/p&gt;

&lt;p&gt;A full data grid component comes with a more complete UI, including built-in interactions and configurable behavior. For teams that need a spreadsheet-like experience without implementing every interaction from scratch, this can save substantial development time.&lt;/p&gt;

&lt;p&gt;The challenge is finding a grid that handles your dataset, fits your framework, and includes the features your application needs without creating unnecessary bundle weight or licensing costs.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Features Really Matter in a Web Data Grid?
&lt;/h2&gt;

&lt;p&gt;When choosing an open-source data grid, start with a practical checklist: performance, data operations, editing, customization, framework compatibility, accessibility, and licensing. The right balance depends on your application's workload and the experience your users expect.&lt;/p&gt;

&lt;p&gt;Here are the capabilities worth evaluating before committing to a library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Virtual scrolling:&lt;/strong&gt; Keeps large datasets responsive by rendering visible rows and a small buffer instead of mounting every row in the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sorting and filtering:&lt;/strong&gt; Supports everyday data exploration, including multi-column sorting, advanced filter conditions, and server-side operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selection and editing:&lt;/strong&gt; Provides cell and range selection, keyboard navigation, inline editing, and spreadsheet-style conveniences such as a fill handle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization and theming:&lt;/strong&gt; Lets you create custom cell renderers, format values, apply application-specific styling, and support dark mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript and framework support:&lt;/strong&gt; Offers reliable types and bindings that fit your existing React, Vue, or Angular application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle size and dependencies:&lt;/strong&gt; Affects initial loading costs and the number of third-party packages your project must maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility and keyboard support:&lt;/strong&gt; Makes common grid interactions available through the keyboard and provides appropriate accessibility semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Licensing:&lt;/strong&gt; Clarifies whether grouping, pivot tables, and other advanced features are available under the free license.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That final point deserves attention. A library can be free to install while charging for the capabilities your application eventually needs. Check the licensing of individual features before making your decision.&lt;/p&gt;

&lt;p&gt;gp-grid addresses this checklist with a TypeScript-first architecture, virtual scrolling, spreadsheet-style interactions, and an Apache 2.0 license that covers its complete feature set.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is gp-grid?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gp-grid.io/" rel="noopener noreferrer"&gt;gp-grid&lt;/a&gt; is an &lt;a href="https://github.com/GioPat/gp-grid" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; TypeScript data grid for React, Vue, and Angular, built around virtual scrolling, a framework-agnostic core, and a data-source abstraction. The library is released under Apache 2.0 and announces its 1.0.0 release with all features available for free.&lt;/p&gt;

&lt;p&gt;Its architecture follows three main principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slot-based virtual scrolling:&lt;/strong&gt; gp-grid recycles a pool of DOM containers as users scroll, keeping the number of rendered elements controlled even when the underlying dataset contains millions of rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instruction-based core:&lt;/strong&gt; The core emits declarative instructions describing UI changes, separating grid logic from framework-specific rendering and allowing the wrappers to share the same underlying behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible data sources:&lt;/strong&gt; You can work with data held in browser memory or fetch rows from a server on demand, depending on your application's needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project separates its functionality into four packages: &lt;code&gt;@gp-grid/core&lt;/code&gt;, &lt;code&gt;@gp-grid/react&lt;/code&gt;, &lt;code&gt;@gp-grid/vue&lt;/code&gt;, and &lt;code&gt;@gp-grid/angular&lt;/code&gt;. They are available through &lt;a href="https://www.npmjs.com/org/gp-grid" rel="noopener noreferrer"&gt;npm&lt;/a&gt; and &lt;a href="https://jsr.io/@gp-grid" rel="noopener noreferrer"&gt;JSR&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Installation and Quick Start: React, Vue, and Angular
&lt;/h2&gt;

&lt;p&gt;Getting started with gp-grid requires installing the package for your framework, defining your columns, and providing your data. The library recommends TypeScript 5.0 or higher, includes its own type definitions, and supports React 18+ and Vue 3 through dedicated wrappers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Install the package
&lt;/h3&gt;

&lt;p&gt;Choose the framework package you need and install it with your preferred package manager:&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; @gp-grid/&amp;lt;framework&amp;gt;
&lt;span class="c"&gt;# Replace &amp;lt;framework&amp;gt; with react, vue, or angular&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The package names and component bindings are summarized below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Data helper&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@gp-grid/react&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Grid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useGridData&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vue&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@gp-grid/vue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GpGrid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;createGridData&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Angular&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@gp-grid/angular&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gp-grid&lt;/code&gt; (&lt;code&gt;GpGridComponent&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;provideGridData&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom adapter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@gp-grid/core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GridCore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;createClientDataSource&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Build your first React data grid
&lt;/h3&gt;

&lt;p&gt;Define your columns and pass them to the &lt;code&gt;Grid&lt;/code&gt; component alongside your rows. This example includes an editable name column and a basic email column.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;Grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ColumnDefinition&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;@gp-grid/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@gp-grid/react/dist/styles.css&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;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ColumnDefinition&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cellDataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;headerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID&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="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cellDataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&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="na"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cellDataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;headerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&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="mi"&gt;1&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alice@example.com&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="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bob@example.com&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;400px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt; &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;rowData&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;rowHeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;One detail can save you a frustrating debugging session: &lt;strong&gt;the grid fills its parent, so that parent needs an explicit height.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Remember to import the stylesheet once at your application's root. Vue and Angular use their own component bindings but follow the same column-definition model.&lt;/p&gt;


&lt;h2&gt;
  
  
  gp-grid Core Features
&lt;/h2&gt;

&lt;p&gt;The core features of gp-grid cover performance, data exploration, spreadsheet-style editing, customization, and different ways of loading data. Here are the capabilities worth examining when deciding whether the library fits your application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Slot-Based Virtual Scrolling and Million-Row Performance
&lt;/h3&gt;

&lt;p&gt;gp-grid uses slot-based virtualization to keep the rendered DOM small as datasets grow. Starting with version 1.0.0, it virtualizes the entire grid viewport, including both rows and columns. It maintains reusable DOM containers and updates their assignments as users scroll vertically or horizontally, rendering only the visible area and the surrounding overscan buffer.&lt;/p&gt;

&lt;p&gt;The same overscan logic applies to both dimensions, helping preserve smooth scrolling behavior in both directions. This means gp-grid can handle large datasets and wide grids without mounting every row and column in the DOM. By reusing rendering slots as the viewport moves, it reduces the overhead associated with repeatedly creating and destroying DOM elements.&lt;/p&gt;

&lt;p&gt;For large client-side datasets, sorting can also run in a Web Worker, enabled by default in the client data source. Developers can tune &lt;code&gt;overscan&lt;/code&gt;, &lt;code&gt;wheelDampening&lt;/code&gt;, and &lt;code&gt;maxFlingVelocity&lt;/code&gt; to adjust scrolling behavior for their interface and input devices.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://gp-grid.io/docs/benchmarks" rel="noopener noreferrer"&gt;gp-grid's benchmarks&lt;/a&gt;, its test with one million rows recorded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;56.2 average FPS&lt;/strong&gt; while scrolling, with zero dropped frames.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;652 ms&lt;/strong&gt; for ascending sorting and &lt;strong&gt;188 ms&lt;/strong&gt; for text filtering.&lt;/li&gt;
&lt;li&gt;Approximately &lt;strong&gt;254.7 MB&lt;/strong&gt; of memory after loading the dataset.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results are promising, but they're not universal performance guarantees. The benchmark tested &lt;code&gt;@gp-grid/react&lt;/code&gt; 0.19.0, so keep that version in mind when comparing the figures with the project's newer 1.0 release.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tIcdciyyLe0" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Multi-Column Sorting and Advanced Filtering
&lt;/h3&gt;

&lt;p&gt;Sorting and filtering help users find useful information without manually scanning thousands of records. gp-grid enables sorting by default: clicking a column header changes its sort order, while holding Shift and clicking another header adds a secondary sort criterion.&lt;/p&gt;

&lt;p&gt;Filter controls support text, numeric, and date operators, along with a checkbox-based mode for selecting distinct values. For more complex searches, users can combine conditions with AND/OR logic, making expressions such as &lt;code&gt;(A AND B) OR C&lt;/code&gt; possible.&lt;/p&gt;

&lt;p&gt;You can disable sorting globally through &lt;code&gt;sortingEnabled&lt;/code&gt; or set &lt;code&gt;sortable: false&lt;/code&gt; on an individual column. Custom comparators and custom filter components also provide room for application-specific behavior.&lt;/p&gt;

&lt;p&gt;For example, a finance dashboard could sort transactions by date and then amount, while a CRM user could filter contacts by status and region. These operations are available without requiring a separate enterprise feature license.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CylzevoSJzg" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Cell Selection, Keyboard Navigation, and Excel-Like Editing
&lt;/h3&gt;

&lt;p&gt;gp-grid supports cell selection, drag-to-select ranges, Shift-click to extend a selection, and Ctrl-click to toggle individual cells. Keyboard navigation includes arrow keys, Tab, Enter, Home, End, and common Ctrl-based shortcuts, allowing users to work through data without constantly reaching for the mouse.&lt;/p&gt;

&lt;p&gt;To enable inline editing, set &lt;code&gt;editable: true&lt;/code&gt; on a column. Users can start editing with a double-click, Enter, F2, or by typing. Enter and Tab commit changes, while Escape cancels an edit.&lt;/p&gt;

&lt;p&gt;The fill handle adds another useful spreadsheet-style interaction: users can drag the small handle at the corner of a selected range to copy values across the target cells. Custom edit renderers and validators can support more specialized inputs and validation rules.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/igLTAVciVlA" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom Renderers, Styling, Highlighting, and Dark Mode
&lt;/h3&gt;

&lt;p&gt;A data grid needs to fit your application's interface, especially when cells communicate status, money, dates, or other values that benefit from custom presentation. gp-grid supports custom cell, edit, and header renderers, either directly in column definitions or through renderer registries.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;valueFormatter&lt;/code&gt; option is useful when the displayed value differs from the raw data. For example, a salary column can show currency formatting while sorting and value-based operations continue to use the underlying numeric value.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;salary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cellDataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cellRenderer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SalaryRenderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;valueFormatter&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;as &lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&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;Styling is also flexible. The &lt;code&gt;darkMode&lt;/code&gt; prop enables dark styling, and the built-in CSS uses zero-specificity &lt;code&gt;:where()&lt;/code&gt; selectors, making it easier to override defaults with your own classes. Tailwind's &lt;code&gt;@apply&lt;/code&gt; directive is supported, while highlighting callbacks can add row, column, or cell classes for hover states, alternating rows, and crosshair effects.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/HlflZ_0tEvQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Live Data Streaming and Server-Side Data
&lt;/h3&gt;

&lt;p&gt;gp-grid supports both continuously changing datasets and data loaded from a server on demand. This makes it suitable for interfaces such as stock tickers, operational dashboards, and administrative tools where records can change while users are working.&lt;/p&gt;

&lt;p&gt;For live updates in React, the &lt;code&gt;useGridData&lt;/code&gt; hook provides a mutable data source with helpers such as &lt;code&gt;addRows&lt;/code&gt; and &lt;code&gt;removeRows&lt;/code&gt;. You can also update individual cells or rows through the data source. Its &lt;code&gt;debounceMs&lt;/code&gt; option batches rapid changes into fewer transactions, helping the grid handle frequent updates efficiently.&lt;/p&gt;

&lt;p&gt;When your dataset is too large to keep entirely in browser memory, &lt;code&gt;createServerDataSource&lt;/code&gt; lets the grid request specific row ranges from your API, along with sorting and filtering information.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;Grid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createServerDataSource&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;@gp-grid/react&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;dataSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerDataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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;res&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/grid-data&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="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;request&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;res&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="c1"&gt;// { rows, totalRows }&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Grid&lt;/span&gt; &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dataSource&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;rowHeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Your endpoint must return the requested rows and the total row count. For datasets exceeding roughly 10 million rows, gp-grid's performance guide recommends server-side data loading.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/p5HRxA4GFEs" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Flexible Layout: Drag, Resize, Pin, Freeze, and Group Columns
&lt;/h3&gt;

&lt;p&gt;A useful data grid should let users arrange information around their workflow. gp-grid supports dragging columns into a new order, resizing columns with minimum and maximum constraints, pinning columns to either side, and freezing rows beneath the header.&lt;/p&gt;

&lt;p&gt;Column virtualization also limits the number of mounted columns when working with wide datasets. The grid supports right-to-left layouts, configurable column sizing, nested column groups, and row heights that can vary by row identity.&lt;/p&gt;

&lt;p&gt;For example, a CRM could keep contact names visible while users scroll horizontally through company details, activity dates, and account values. A financial dashboard could freeze important summary rows while users inspect the records below them.&lt;/p&gt;

&lt;p&gt;The library also provides ARIA grid roles and keyboard support. However, its documentation does not claim full accessibility compliance, so applications with strict accessibility requirements should perform their own audits and testing.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/EPf9ulynBdo" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Row Grouping, Aggregation, and Pivot Tables
&lt;/h3&gt;

&lt;p&gt;gp-grid includes row grouping, aggregation, and pivot tables under its free Apache 2.0 license. These features help turn flat records into structured summaries, giving users ways to explore large datasets without requiring a separate enterprise license.&lt;/p&gt;

&lt;p&gt;Row grouping organizes records into expandable groups, with aggregates and totals available for summarizing values. Depending on the data source, grouping calculations can happen locally or be loaded from the server on demand.&lt;/p&gt;

&lt;p&gt;Pivot tables let you transform dimensions into columns and summarize the resulting data, either locally or through precomputed pivot tables. This is useful for analytical interfaces where users need to compare categories, examine totals, or reorganize information around different dimensions.&lt;/p&gt;

&lt;p&gt;The project also provides further guides covering write commands, history, and columnar data sources. Because gp-grid is a young project, review the relevant guides and try these capabilities with your own data before making them a core dependency.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/9QyD9leR--4" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you want to explore the examples yourself, I've published the complete gp-grid playground on GitHub. &lt;/p&gt;

&lt;p&gt;Clone the repository, run it locally, and experiment with all seven interactive demos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Hadil-Ben-Abdallah/gp-grid-playground" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐ gp-grid Playground Demo&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  Onboard Your AI Coding Agent With the Official gp-grid Skill
&lt;/h2&gt;

&lt;p&gt;AI coding agents can save time when building data-heavy interfaces, but they need accurate library-specific guidance to generate code that works. gp-grid provides an &lt;a href="https://gp-grid.io/docs/onboard-your-llm" rel="noopener noreferrer"&gt;official skill&lt;/a&gt; that helps coding agents use the correct imports, column definitions, renderers, and data-source APIs across its supported frameworks.&lt;/p&gt;

&lt;p&gt;The skill includes a main &lt;code&gt;SKILL.md&lt;/code&gt; file and framework-specific references for React, Vue, Angular, and the framework-agnostic core. It also covers common integration mistakes, such as forgetting to set the grid container's height, missing the stylesheet import, or using the wrong date data type.&lt;/p&gt;

&lt;p&gt;Install it from your project with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/GioPat/gp-grid

&lt;span class="c"&gt;# Update later&lt;/span&gt;
npx skills add GioPat/gp-grid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The skill can help agents choose between client-side data, live updates, and server-side loading, including the correct &lt;code&gt;{ startRow, endRow }&lt;/code&gt; request shape for server-side data.&lt;/p&gt;


&lt;h2&gt;
  
  
  gp-grid vs AG Grid: Features, Cost, and Performance
&lt;/h2&gt;

&lt;p&gt;Choosing a React data grid involves more than comparing performance. Feature availability and licensing can have a major impact on the total cost of a project. AG Grid follows a Community and Enterprise model: its Community edition is free, but several advanced capabilities, including row grouping and pivoting, require an Enterprise license. gp-grid takes a different approach by making all its features available under the Apache 2.0 license, with no Enterprise tier or feature-based licensing restrictions.&lt;/p&gt;

&lt;p&gt;The following comparison uses results from gp-grid's July 2026 benchmark, which tested one million rows using the same seeded data and column definitions. These are results from a specific test environment and workload, not universal performance guarantees.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;gp-grid&lt;/th&gt;
&lt;th&gt;AG Grid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;td&gt;MIT Community / commercial Enterprise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package size (Bundlephobia, minified and gzipped)&lt;/td&gt;
&lt;td&gt;~80 kB, before application-level tree-shaking&lt;/td&gt;
&lt;td&gt;306.7 kB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime dependencies&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average scrolling FPS&lt;/td&gt;
&lt;td&gt;56.2&lt;/td&gt;
&lt;td&gt;41.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dropped frames during measured scroll&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ascending sort, 1M rows&lt;/td&gt;
&lt;td&gt;652 ms&lt;/td&gt;
&lt;td&gt;2,104 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-column sort, 1M rows&lt;/td&gt;
&lt;td&gt;1,219.5 ms&lt;/td&gt;
&lt;td&gt;3,044.5 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text filter, 1M rows&lt;/td&gt;
&lt;td&gt;188 ms&lt;/td&gt;
&lt;td&gt;327 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full initial render, 1M rows&lt;/td&gt;
&lt;td&gt;1,493.5 ms&lt;/td&gt;
&lt;td&gt;2,530 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory after loading 1M rows&lt;/td&gt;
&lt;td&gt;254.7 MB&lt;/td&gt;
&lt;td&gt;461.9 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row grouping and pivoting&lt;/td&gt;
&lt;td&gt;Included free&lt;/td&gt;
&lt;td&gt;Enterprise features&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;gp-grid stands out when you want advanced data-grid capabilities without paying for an Enterprise license. It is worth considering for applications that need grouping, pivoting, virtual scrolling, editing, and other advanced features under one open-source license, alongside a smaller React bundle in the benchmark.&lt;/p&gt;

&lt;p&gt;AG Grid can be a strong choice when your project already relies on its ecosystem, documentation, integrations, or established Community and Enterprise offerings. Its Community edition may be sufficient for applications that only need its free features, while teams that need Enterprise functionality can evaluate whether the commercial license fits their requirements.&lt;/p&gt;


&lt;h2&gt;
  
  
  Who Should Use gp-grid?
&lt;/h2&gt;

&lt;p&gt;gp-grid is worth considering if you need a feature-rich, open-source data grid without an enterprise license. It can be a good fit for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Teams building data-heavy dashboards:&lt;/strong&gt; Virtual scrolling and server-side loading help applications work with large datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers who need advanced features for free:&lt;/strong&gt; Row grouping, pivot tables, cell selection, inline editing, and column pinning are included without paid feature tiers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript-first projects:&lt;/strong&gt; Built-in type definitions support typed column configurations and editor autocomplete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams working across frontend frameworks:&lt;/strong&gt; Dedicated packages support React, Vue 3, and Angular, with a framework-agnostic core for custom integrations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projects with strict bundle or dependency requirements:&lt;/strong&gt; The library has zero external runtime dependencies, and its published React bundle measurement is worth evaluating for performance-conscious applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers using AI coding agents:&lt;/strong&gt; The official gp-grid skill provides framework-specific guidance and examples to help agents generate compatible integrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;If you find this useful, consider starring the GitHub repo&lt;/strong&gt;; it helps support the open-source project and its continued development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GioPat/gp-grid" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐ Star gp-grid on GitHub&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  What is the best free data grid for React?
  &lt;br&gt;
The right choice depends on the features your application needs. gp-grid is worth considering if you want an open-source React data grid with virtual scrolling, editing, row grouping, and pivoting included under the Apache 2.0 license. If you prefer to build your own markup and interaction layer, a headless library such as TanStack Table may fit better.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Is gp-grid really free, or are there paid features?
  &lt;br&gt;
gp-grid's features are available under the Apache 2.0 license, with no enterprise tier or paywalled feature modules described by the project. The maintainer accepts optional donations, but the library's advanced capabilities are not gated behind a commercial license.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Does gp-grid support Angular, Vue, and TypeScript?
  &lt;br&gt;
Yes. gp-grid provides dedicated packages for React, Vue, and Angular, alongside a framework-agnostic core. It is written in TypeScript and includes type definitions, so developers can use typed column definitions and editor autocomplete without installing separate &lt;code&gt;@types&lt;/code&gt; packages.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Can a React data grid handle one million rows?
  &lt;br&gt;
Yes, with an appropriate rendering and data-loading strategy. Virtual scrolling limits the number of rows rendered in the DOM, while server-side data loading lets the application request only the records it needs. gp-grid's published one-million-row benchmark reports 56.2 average FPS during its measured scroll test, but actual results depend on the application and environment.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What is the best free alternative to AG Grid Enterprise?
  &lt;br&gt;
gp-grid is one option to evaluate if you need features such as row grouping and pivoting without an enterprise license. Its published benchmark also reports lower bundle size and faster results for several tested operations. AG Grid has a more established ecosystem, so compare your required features, support needs, and real-world workload before choosing.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;


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

&lt;p&gt;Choosing an open-source data grid means looking at more than its license. Performance, editing, customization, data loading, framework support, and the long-term health of the project all affect whether it will serve your application well.&lt;/p&gt;

&lt;p&gt;gp-grid brings these concerns together in a TypeScript-first library with virtual scrolling, React/Vue/Angular bindings, and advanced features available without paid tiers. Its benchmark results are promising, although the project is still young and the published test has limitations.&lt;/p&gt;

&lt;p&gt;In this article, I explored gp-grid and its key features. In the next article, I’ll put it to the test by building a real React project, sharing the development process, what worked well, and the challenges I encountered along the way. Stay tuned for a hands-on look at building with gp-grid!&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>programming</category>
      <category>react</category>
      <category>vue</category>
      <category>angular</category>
    </item>
    <item>
      <title>Your SaaS Has 10,000 Users. Who Removes Their Access When They Leave?</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Wed, 28 Oct 2026 09:52:39 +0000</pubDate>
      <link>https://dev.to/hadil/your-saas-has-10000-users-who-removes-their-access-when-they-leave-2676</link>
      <guid>https://dev.to/hadil/your-saas-has-10000-users-who-removes-their-access-when-they-leave-2676</guid>
      <description>&lt;p&gt;SaaS user deprovisioning is one of those responsibilities that's easy to overlook when you're building an authentication system. A user leaves a customer’s company, an administrator removes their account, and everyone assumes their access has been taken care of. &lt;/p&gt;

&lt;p&gt;But has it?&lt;/p&gt;

&lt;p&gt;Imagine your SaaS product has 10,000 users across hundreds of customer organizations. One of those customers tells you that an employee has left the company. Their administrator removes the employee from the organization, expecting their access to disappear immediately.&lt;/p&gt;

&lt;p&gt;What happens next depends on how your application handles account status, active sessions, access tokens, and connected services. If those pieces aren't coordinated, a user who should have lost access may still be able to reach parts of your product.&lt;/p&gt;

&lt;p&gt;This becomes harder to manage as your customer base grows. Enterprise customers may use single sign-on (SSO), central identity providers, and automated user provisioning. Your SaaS application still needs a reliable way to respond when someone loses access, changes roles, or leaves the organization entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The customer's administrator or identity provider may initiate the process, but your SaaS application must enforce the removal of access to its own resources. Your identity platform can help coordinate the process, depending on how you've implemented authentication and provisioning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When an employee leaves:&lt;/strong&gt; The customer's identity provider or administrator can disable the account or remove the user from the relevant application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When your SaaS receives the change:&lt;/strong&gt; Your application must update the user's access, revoke applicable sessions, and prevent further unauthorized requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When SSO is enabled:&lt;/strong&gt; Blocking sign-in at the identity provider helps, but existing application sessions and issued tokens need to be handled too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When customers use SCIM:&lt;/strong&gt; Automated provisioning and deprovisioning can communicate user and membership changes between an identity provider and your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When your SaaS grows:&lt;/strong&gt; Keycloak can provide a centralized identity layer for authentication across customer organizations. If you want to use Keycloak without operating the identity infrastructure yourself, &lt;a href="https://skycloak.io/hosting/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_deprovisioning" rel="noopener noreferrer"&gt;Skycloak offers managed Keycloak hosting&lt;/a&gt;. Your application still needs to handle provisioning, authorization, and access revocation according to your architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key takeaway: &lt;strong&gt;removing a user's ability to sign in again doesn't automatically guarantee that every existing session or permission has been revoked.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Your SaaS needs a defined offboarding process that covers the access your application actually controls.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When a SaaS User Leaves?
&lt;/h2&gt;

&lt;p&gt;Let's follow a realistic example. A company uses your SaaS product to manage internal projects. One of its employees leaves, and the company's IT administrator disables that employee's account in the corporate identity provider.&lt;/p&gt;

&lt;p&gt;That action changes what the employee can do, but the result depends on how your product integrates with the identity provider.&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%2F5lims7b0btwsoxnyr5cw.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%2F5lims7b0btwsoxnyr5cw.png" alt="SaaS user deprovisioning flow showing an identity provider disabling a user and the SaaS application revoking sessions, tokens, and resource access" width="799" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking the Next Login Is Only the First Step
&lt;/h3&gt;

&lt;p&gt;If the employee tries to sign in again through the corporate identity provider, the disabled account should prevent a successful new login. That's an important first step, but your SaaS may already have an authenticated session for that user.&lt;/p&gt;

&lt;p&gt;For example, the application may have issued its own session cookie after the original SSO login. Disabling the identity-provider account doesn't necessarily invalidate that application session automatically. The application needs a way to detect the account's changed status and reject access when appropriate.&lt;/p&gt;

&lt;p&gt;The same concern applies to access tokens. A self-contained token, such as a JWT, can remain valid until it expires unless the resource server has a mechanism to check revocation or current authorization. The exact behavior depends on your token design and validation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing Access Across the Product
&lt;/h3&gt;

&lt;p&gt;There's another layer to consider: what the user was allowed to do after signing in.&lt;/p&gt;

&lt;p&gt;A former employee might have had access to shared projects, customer records, API credentials, or administrative functions. If their membership or role remains active in your application, blocking their next login alone doesn't clean up those permissions.&lt;/p&gt;

&lt;p&gt;A reliable offboarding flow needs to address the relevant parts of the account lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Prevent the user from establishing new sessions when their account is disabled or access is withdrawn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active sessions:&lt;/strong&gt; Invalidate applicable sessions and account for tokens that may remain valid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization:&lt;/strong&gt; Remove organization membership, roles, and permissions that the user should no longer have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connected systems:&lt;/strong&gt; Revoke or update access to integrations, API keys, and other resources where your application manages those credentials or permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not every product needs the same implementation. A simple SaaS application may have a single user account and a few organization roles. An enterprise platform with multiple integrations may need a coordinated workflow across several systems.&lt;/p&gt;

&lt;p&gt;The important part is defining what offboarding means for your product and ensuring that each relevant layer enforces it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Manual Offboarding Breaks as Your SaaS Grows
&lt;/h2&gt;

&lt;p&gt;When you have a handful of customers, removing a user might be a simple database update. An administrator disables the account, your application blocks access, and the process is complete. At 10,000 users across hundreds of organizations, the same approach becomes harder to maintain.&lt;/p&gt;

&lt;p&gt;The problem is that user changes can originate in different places. One customer manages accounts directly in your product, another relies on Microsoft Entra ID or Okta, and a third connects an external identity provider through SSO. Each setup creates a different path for communicating that a user's access has changed.&lt;/p&gt;

&lt;p&gt;Manual processes also introduce delays. An IT administrator might disable an employee's corporate account but forget to remove their membership from your SaaS application. A customer might notify your support team, which then has to locate the correct account and make the change manually. Every additional step creates another opportunity for access to remain active longer than intended.&lt;/p&gt;

&lt;p&gt;Three challenges tend to become more significant as your customer base grows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent account management:&lt;/strong&gt; Different customers use different identity providers, account policies, and offboarding procedures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delayed access removal:&lt;/strong&gt; Your application may not learn about an account change until someone manually updates it or the user attempts to sign in again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unclear ownership:&lt;/strong&gt; Your team may assume the customer's identity provider handles everything, while the customer assumes your application removes all access automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A scalable approach needs a clear source of identity information, a reliable way to communicate account changes, and application logic that applies those changes correctly. That's where automated provisioning becomes useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  How SCIM Helps Automate SaaS User Deprovisioning
&lt;/h2&gt;

&lt;p&gt;System for Cross-domain Identity Management (SCIM) is a standard for exchanging identity information between systems. It allows an identity provider to create, update, and deactivate user accounts in a connected application through a defined API.&lt;/p&gt;

&lt;p&gt;For enterprise SaaS products, SCIM can reduce the manual work involved in managing customer users throughout their lifecycle. When an employee joins an organization, the identity provider can provision an account in your product. When that employee changes roles or leaves, the provider can send an update that your application processes.&lt;/p&gt;

&lt;p&gt;A typical workflow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An administrator changes the user's status.&lt;/strong&gt; The customer's IT team disables the employee or removes their assignment to your application in the identity provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The identity provider sends a provisioning request.&lt;/strong&gt; Depending on the provider and configuration, it may deactivate the SCIM user resource, delete it, or update its attributes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your application processes the change.&lt;/strong&gt; It identifies the correct user and organization, updates the account's status, and applies the appropriate access-removal rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The application handles existing access.&lt;/strong&gt; It invalidates applicable sessions, updates memberships and permissions, and addresses tokens or credentials according to its security design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The operation is recorded.&lt;/strong&gt; Logs and provisioning status help administrators investigate failures and confirm whether the change was applied.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SCIM standardizes communication between systems, but it doesn't automatically secure every layer of your application. Your implementation must correctly interpret incoming changes, handle errors, and enforce the resulting access decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens When a SCIM Request Fails?
&lt;/h3&gt;

&lt;p&gt;Consider an identity provider that sends a deactivation request while your application is temporarily unavailable. If your endpoint returns an error and the provider retries the request, the change may eventually succeed. If your system drops the event without recording it, the user could remain active.&lt;/p&gt;

&lt;p&gt;For that reason, a production-ready implementation should handle retries, duplicate requests, and partial failures. Processing the same deactivation request more than once should not cause problems, and your system should make failures visible to the appropriate administrators.&lt;/p&gt;

&lt;p&gt;You should also distinguish between disabling a user account and deleting its record. Deactivation can preserve the user's historical activity, audit records, and references in shared resources. Permanent deletion may be appropriate in some situations, but it can introduce complications when other records depend on that user.&lt;/p&gt;

&lt;p&gt;The right behavior depends on your product's data model, retention requirements, and customer agreements. Define these rules before connecting SCIM to your production environment.&lt;/p&gt;

&lt;p&gt;The key benefit is consistency. SCIM gives your SaaS a standard way to receive identity lifecycle changes, while your application remains responsible for enforcing those changes.&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%2Fov1isskm8phpm0vj3sl4.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%2Fov1isskm8phpm0vj3sl4.png" alt="SaaS user deprovisioning architecture showing SCIM sending account deactivation events from an identity provider to a SaaS application to update user status, memberships, sessions, and permissions" width="799" height="336"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Keycloak Fits Into SaaS User Deprovisioning
&lt;/h2&gt;

&lt;p&gt;If your SaaS supports enterprise SSO, a centralized identity platform can simplify authentication across customer organizations. Keycloak is one option for managing authentication, identity brokering, and access-related configuration through a common identity layer.&lt;/p&gt;

&lt;p&gt;For example, your application can use OpenID Connect (OIDC) or SAML to authenticate users through Keycloak. Depending on your configuration, Keycloak can connect to an external identity provider and manage the authentication flow between that provider and your application.&lt;/p&gt;

&lt;p&gt;This provides a useful foundation, but &lt;strong&gt;authentication and deprovisioning are related responsibilities, not the same operation&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Centralized Authentication Doesn't Remove Every Application Permission
&lt;/h3&gt;

&lt;p&gt;Imagine a customer uses its corporate identity provider to authenticate employees through Keycloak. When an employee leaves, the corporate account is disabled. Your SaaS still needs to determine how that change reaches Keycloak and the application, and what happens to existing access.&lt;/p&gt;

&lt;p&gt;Depending on the integration, you may need to account for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity synchronization:&lt;/strong&gt; How changes from the customer's identity provider reach Keycloak or your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session management:&lt;/strong&gt; How applicable Keycloak sessions and application sessions are invalidated when access is withdrawn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application authorization:&lt;/strong&gt; How your product removes organization memberships, roles, and permissions that are no longer appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provisioning integrations:&lt;/strong&gt; How users and their lifecycle changes are synchronized through SCIM or another supported mechanism.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact setup depends on your architecture. Keycloak's authentication protocols don't, by themselves, guarantee that every customer identity change will trigger complete deprovisioning in every connected system. Keycloak 26.6 and later includes a native SCIM 2.0 API for user and group provisioning. Skycloak makes &lt;a href="https://skycloak.io/features/scim/" rel="noopener noreferrer"&gt;SCIM provisioning&lt;/a&gt; available on all plans, allowing teams to synchronize user lifecycle changes through a standard interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Keycloak Handles User Logout and Token Expiration
&lt;/h3&gt;

&lt;p&gt;When an administrator disables a user in Keycloak, the user cannot establish new authenticated sessions, and refresh-token requests for that disabled user fail. However, an access token that has already been issued can remain valid until it expires. Keycloak's default access-token lifespan is five minutes, although this value can be changed in the realm settings.&lt;/p&gt;

&lt;p&gt;To terminate the user's Keycloak sessions immediately, an administrator can open &lt;strong&gt;Users → select the user → Sessions → Sign out&lt;/strong&gt;. The same operation is available through the Admin REST API:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;POST /admin/realms/{realm}/users/{id}/logout&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To close the user's application session as well, configure the client's &lt;strong&gt;Backchannel Logout URL&lt;/strong&gt; and implement the corresponding logout endpoint in your application. Keycloak can then send a logout request to the application when the user's session is terminated. Your application must process that request and invalidate its own session.&lt;/p&gt;

&lt;p&gt;This distinction matters for SaaS user deprovisioning: terminating a Keycloak session and revoking access to every application resource are separate steps. Your application must also enforce its authorization rules and account for access tokens that remain valid until expiration. &lt;/p&gt;




&lt;h2&gt;
  
  
  Managing Your Keycloak Infrastructure with Skycloak
&lt;/h2&gt;

&lt;p&gt;Building a reliable SaaS user deprovisioning workflow requires an identity platform that supports your authentication and provisioning needs as your customer base grows.&lt;/p&gt;

&lt;p&gt;Self-hosting Keycloak gives your team control over the deployment, but your team is also responsible for the infrastructure, updates, monitoring, and ongoing maintenance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skycloak.io/" rel="noopener noreferrer"&gt;Skycloak&lt;/a&gt; provides &lt;a href="https://skycloak.io/hosting/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_deprovisioning" rel="noopener noreferrer"&gt;managed Keycloak hosting&lt;/a&gt;, handling the identity infrastructure while your team focuses on its application. Every plan includes unlimited users and full Keycloak admin access. Skycloak supports deployments in the US, EU, Canada, and Australia, giving teams regional hosting options. You can also start a 21-day free trial without a credit card.&lt;/p&gt;

&lt;p&gt;Skycloak includes &lt;a href="https://skycloak.io/features/scim/" rel="noopener noreferrer"&gt;SCIM 2.0 provisioning&lt;/a&gt; on all plans, with support for automated user provisioning, deprovisioning, and group synchronization with compatible identity providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Managed Keycloak Fits Into User Offboarding
&lt;/h3&gt;

&lt;p&gt;Your team can use Keycloak to manage authentication while its application handles the consequences of account changes: organization memberships, roles, permissions, active sessions, and access to connected resources.&lt;/p&gt;

&lt;p&gt;Skycloak manages the Keycloak hosting infrastructure. Your application remains responsible for applying account status changes and enforcing authorization rules, including revoking access that the application controls.&lt;/p&gt;

&lt;p&gt;For example, when an employee leaves a customer's organization, SCIM can communicate the lifecycle change to the connected identity system. Your SaaS application must then process that change, update the relevant account and membership records, and handle existing sessions and access tokens according to its security design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Managed Keycloak Right for Your SaaS?
&lt;/h3&gt;

&lt;p&gt;Skycloak offers unlimited users and full Keycloak admin access on every plan, with regional hosting options in the US, EU, Canada, and Australia. Its 21-day free trial does not require a credit card.&lt;/p&gt;

&lt;p&gt;Explore &lt;a href="https://skycloak.io/pricing/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_deprovisioning" rel="noopener noreferrer"&gt;Skycloak's managed Keycloak hosting plans&lt;/a&gt; to compare the available options for your SaaS.&lt;/p&gt;

&lt;p&gt;Managed identity infrastructure reduces the operational work involved in running Keycloak. Pairing it with a well-defined offboarding process helps your application enforce access changes consistently across users, sessions, memberships, and protected resources.&lt;/p&gt;




&lt;h2&gt;
  
  
  Designing a Reliable Offboarding Flow
&lt;/h2&gt;

&lt;p&gt;A dependable SaaS user deprovisioning process starts with a simple question: &lt;strong&gt;When an organization removes a user, what must happen before that user's access is considered revoked?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Write down the expected behavior for each type of account your product supports. A user managed directly by a customer administrator may follow a different path from a user provisioned through SCIM or authenticated through an external identity provider. Those paths should still lead to a consistent security outcome.&lt;/p&gt;

&lt;p&gt;Use the following checklist when designing your flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identify the source of the change.&lt;/strong&gt; Determine whether the request comes from your own admin interface, an identity provider, a SCIM endpoint, or another trusted integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the affected account and organization.&lt;/strong&gt; Make sure a change for one customer cannot disable a user or remove permissions in another customer's organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update account status and memberships.&lt;/strong&gt; Apply the change to the correct user record, organization membership, roles, and permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle active access.&lt;/strong&gt; Invalidate applicable sessions and account for outstanding tokens or credentials based on your authentication architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protect connected resources.&lt;/strong&gt; Revoke or update API keys, integration credentials, and other access mechanisms your application controls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record the outcome.&lt;/strong&gt; Log the request, its source, the actions performed, and any failures without exposing secrets or sensitive token values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make failures recoverable.&lt;/strong&gt; Use retries, idempotent processing, and monitoring so a temporary error doesn't silently leave an account active.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the full lifecycle.&lt;/strong&gt; Verify what happens after account deactivation, organization removal, role changes, and provisioning failures, not only whether a new login is blocked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should also decide how quickly access must be revoked. Some products can tolerate a short delay for routine synchronization, while applications handling sensitive customer or financial data may require more immediate enforcement. Your architecture should reflect that requirement, including how frequently it checks authorization state and how long issued tokens remain usable.&lt;/p&gt;

&lt;p&gt;Finally, test the flow from end to end. Disable a test user in the source identity provider, verify that the change reaches your application, and confirm that the user cannot access protected resources through an existing session or previously issued credential. Check the logs as well, so your team can establish what happened and identify any failed step.&lt;/p&gt;

&lt;p&gt;A successful sign-in test is only one part. Your SaaS should be able to demonstrate that an offboarding request reaches the right account, changes the relevant permissions, and prevents access through the paths your application supports.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common SaaS User Deprovisioning Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;Even with SSO, SCIM, and a centralized identity platform in place, gaps can remain in your offboarding process. The most common problems happen when teams assume one successful action automatically handles every other layer of access.&lt;/p&gt;

&lt;p&gt;Here are five mistakes worth checking in your SaaS application.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Assuming SSO Automatically Revokes Existing Access
&lt;/h3&gt;

&lt;p&gt;Disabling a user in an external identity provider can prevent future authentication, but it doesn't necessarily terminate every session already established in your application. Define how your application responds to account changes and how it handles sessions and tokens that remain valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Treating Account Deactivation as Complete Permission Cleanup
&lt;/h3&gt;

&lt;p&gt;A disabled account may still have organization memberships, assigned roles, API keys, or integration credentials recorded in your system. Your offboarding workflow should identify which of these resources need to be removed, disabled, or transferred.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ignoring Failed Provisioning Events
&lt;/h3&gt;

&lt;p&gt;A SCIM request can fail because of a network problem, an invalid resource, or an application error. Without monitoring and a recovery process, your team might never notice that a deactivation was not applied. Log failures, retry safely, and alert the right people when intervention is needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Deleting Accounts Without Considering Audit History
&lt;/h3&gt;

&lt;p&gt;Permanent deletion can break references to past actions, reports, and shared resources. For many SaaS products, deactivating an account and preserving the necessary audit history is a better default. Apply your retention and deletion policies carefully, including any relevant contractual or legal requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Failing to Test Real Offboarding Scenarios
&lt;/h3&gt;

&lt;p&gt;Testing whether a user can sign in after deactivation is useful, but it doesn't cover every access path. Test existing sessions, protected API endpoints, organization membership, privileged actions, and any connected resources your product manages. Include failures and retries in your test cases.&lt;/p&gt;

&lt;p&gt;A strong SaaS user deprovisioning process is one you can test, monitor, and explain. You should be able to identify where a request originated, what your application changed, and whether any step failed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  What is SaaS user deprovisioning?
  &lt;br&gt;
SaaS user deprovisioning is the process of removing or disabling a person's access to a software-as-a-service application when they leave an organization, change roles, or no longer need the product. Depending on the application, this can include deactivating the account, removing organization memberships and permissions, terminating sessions, and addressing associated credentials.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Does disabling a user in SSO remove their access immediately?
  &lt;br&gt;
Not necessarily. Disabling the account in an identity provider can block future authentication, but existing application sessions or previously issued tokens may remain usable, depending on how the application validates them. To enforce timely access removal, your SaaS needs an appropriate session invalidation, token validation, and authorization strategy.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  How does SCIM automate user deprovisioning?
  &lt;br&gt;
SCIM allows an identity provider to communicate user lifecycle changes to a connected application through a standardized API. When a user is deactivated or removed from an application assignment, the provider can send a corresponding request. The SaaS application must process that request correctly and apply its own account, membership, and access-removal rules.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Can Keycloak handle SaaS user deprovisioning?
  &lt;br&gt;
Keycloak can provide identity and authentication capabilities as part of a SaaS user deprovisioning workflow. When a user is disabled, new logins and refresh-token requests for the terminated session fail, but an access token already issued can remain valid until expiration. Keycloak's default access-token lifespan is five minutes, although it is configurable. Administrators can terminate the user's Keycloak sessions and configure backchannel logout so the application can invalidate its own session. The application must still enforce its authorization rules and handle access to protected resources. Teams that want Keycloak without operating its infrastructure can use Skycloak's managed Keycloak hosting. Skycloak includes SCIM 2.0 provisioning on all plans.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Should a SaaS application delete a user or deactivate their account?
  &lt;br&gt;
Deactivation is often a practical first step because it can prevent access while preserving audit history and references to previous activity. Permanent deletion may be appropriate when required by a retention policy, customer request, or applicable legal obligation. The right approach depends on your data model, security requirements, and obligations to your customers.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;




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

&lt;p&gt;When your SaaS has 10,000 users, removing one person's access should not depend on someone remembering every system they might be able to reach. The process needs to work consistently whether the change begins with a customer administrator, an external identity provider, or an automated provisioning workflow.&lt;/p&gt;

&lt;p&gt;SSO helps manage authentication, SCIM 2.0 communicates user lifecycle changes, and Keycloak provides a centralized identity layer. Skycloak offers managed Keycloak hosting with unlimited users, full admin access, and SCIM provisioning on every plan. Whichever deployment model you choose, your application still needs clear rules for account status, organization membership, permissions, and the invalidation of existing access.&lt;/p&gt;

&lt;p&gt;Start by mapping the complete offboarding journey in your product. Decide what should happen when a user is disabled, identify which systems must receive the change, and test what happens when a request fails. Then add monitoring so your team can detect and investigate incomplete operations.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>authentication</category>
      <category>keycloak</category>
      <category>scim</category>
      <category>saas</category>
    </item>
    <item>
      <title>Your Form Says “Submitted”. So Where Did the Lead Go?</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:14:10 +0000</pubDate>
      <link>https://dev.to/yassersoliman/your-form-says-submitted-so-where-did-the-lead-go-4bca</link>
      <guid>https://dev.to/yassersoliman/your-form-says-submitted-so-where-did-the-lead-go-4bca</guid>
      <description>&lt;p&gt;Lead tracking should tell you what happens after someone fills out a form on your website. But what happens when a visitor sees a confirmation message, your analytics records a conversion, and the lead never appears in your CRM?&lt;/p&gt;

&lt;p&gt;For B2B SaaS marketing teams, this gap can create a serious blind spot. A campaign may appear to generate leads, yet sales sees fewer contacts than expected. Marketing starts checking campaign performance, sales questions the lead numbers, and someone eventually has to investigate the website, form integration, and CRM.&lt;/p&gt;

&lt;p&gt;The tricky part is that the form can appear to work perfectly. The visitor submits their details, the page displays a success message, and an analytics event fires. None of those signals proves that the CRM received and saved the lead.&lt;/p&gt;

&lt;p&gt;Reliable lead tracking depends on the full journey from the first form interaction to the contact record in your CRM. Every step needs to pass the right information to the next one, with enough visibility to catch errors before they affect reporting or sales follow-up.&lt;/p&gt;

&lt;p&gt;In this guide, we'll look at where leads can disappear, how to trace a submission through the systems involved, and what B2B SaaS teams can do to make their tracking more reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If a website form shows a successful submission but the lead never reaches your CRM, &lt;strong&gt;check the entire form-to-CRM process, not just the confirmation message or analytics event&lt;/strong&gt;. The problem may come from a failed API request, a broken integration, field mapping errors, validation rules, duplicate handling, or a CRM workflow that rejects or changes the record.&lt;/p&gt;

&lt;p&gt;Start with one test submission and follow it through each stage:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm that the website receives the form data.&lt;/li&gt;
&lt;li&gt;Check whether the form sends the data to the correct integration or endpoint.&lt;/li&gt;
&lt;li&gt;Review integration logs and API responses for errors.&lt;/li&gt;
&lt;li&gt;Verify that the CRM creates the contact or lead record.&lt;/li&gt;
&lt;li&gt;Check field mappings, duplicate rules, assignment settings, and automation.&lt;/li&gt;
&lt;li&gt;Compare form submissions with CRM records and analytics conversions to find gaps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Good lead tracking gives marketing and sales a clearer picture of what actually happened. It also makes problems easier to diagnose before missing leads turn into missed opportunities.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Lead Tracking Can Fail Even When a Form Submission Succeeds
&lt;/h2&gt;

&lt;p&gt;A success message usually confirms that the website has completed a specific step. Depending on how the form is built, it may mean the browser accepted the submission, the server received the request, or a form service returned a successful response.&lt;/p&gt;

&lt;p&gt;That message does not always confirm that the CRM saved a new lead.&lt;/p&gt;

&lt;p&gt;Consider a visitor who fills out a demo request form. The website displays a confirmation message, and Google Analytics records a conversion. However, the integration that sends the visitor's details to the CRM encounters an error. Marketing counts the conversion, but sales never receives the contact.&lt;/p&gt;

&lt;p&gt;From the visitor's perspective, everything worked. From the business's perspective, the lead journey stopped before it reached the sales team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Each System Confirms a Different Part of the Journey
&lt;/h3&gt;

&lt;p&gt;A typical lead journey may involve several separate systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website form:&lt;/strong&gt; Collects the visitor's name, email address, company, and other details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form handler or backend:&lt;/strong&gt; Receives the submission and processes the data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration or API:&lt;/strong&gt; Transfers the lead information to another system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRM:&lt;/strong&gt; Creates or updates the contact or lead record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics and attribution tools:&lt;/strong&gt; Record conversion activity and campaign details.&lt;/li&gt;
&lt;/ul&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%2Fjk2njy5m2att0xr23fh7.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%2Fjk2njy5m2att0xr23fh7.png" alt="Lead tracking flow from website form submission through API integration to CRM and analytics" width="799" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some websites use a form platform that handles several of these steps. Others rely on custom code, automation tools, webhooks, or multiple integrations. The exact setup changes, but the same principle applies: a successful step does not guarantee that every later step succeeded.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Lead Tracking Gaps Affect Marketing and Sales
&lt;/h3&gt;

&lt;p&gt;Missing leads can distort campaign reports, delay sales follow-up, and make a successful campaign look weaker than it really is. The reverse can happen, too: analytics may count repeat submissions or conversions that never become usable CRM records.&lt;/p&gt;

&lt;p&gt;Without reliable lead tracking, teams may struggle to answer basic questions. How many people requested a demo? Which campaigns generated contacts that sales could actually follow up with? Did a drop in leads come from campaign performance or a technical failure?&lt;/p&gt;

&lt;p&gt;Before changing ad budgets or rewriting a landing page, make sure the systems handling the leads are reporting what actually happened.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Common Places a Lead Can Disappear
&lt;/h2&gt;

&lt;p&gt;When a lead fails to reach the CRM, the cause is often somewhere in the handoff between systems. Start by checking the following areas, then use logs and test submissions to narrow down the exact failure point.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Lead Tracking Failures in Form Integrations
&lt;/h3&gt;

&lt;p&gt;A form may collect the visitor's details correctly while the next request fails. The integration might use an expired access token, an incorrect endpoint, a missing permission, or a request format that the receiving service does not accept.&lt;/p&gt;

&lt;p&gt;For example, a CRM API may reject a request because a required field is missing. If the website still shows a generic success message, the visitor may never know that the lead was not saved.&lt;/p&gt;

&lt;p&gt;Check the integration logs, request status, and error response where available. A successful browser interaction alone is not enough to confirm that the CRM received the data.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Field Mapping or Validation Rules Reject the Lead
&lt;/h3&gt;

&lt;p&gt;Even when a request reaches the CRM, the data may not match the fields or rules expected by the system. A form might send a company name under the wrong field, use an unexpected date format, or leave a required CRM field empty.&lt;/p&gt;

&lt;p&gt;Validation rules can also block a record. For example, the CRM may require a lead source, a valid email address, or a value from a predefined list. If the integration sends an unsupported value, the CRM may reject the request or leave the record incomplete.&lt;/p&gt;

&lt;p&gt;Compare the form fields with their destination CRM fields, and check whether the integration transforms values before sending them. Pay attention to recently changed forms, CRM fields, and validation rules, since a small configuration change can interrupt the flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Duplicate Rules Prevent a New Lead From Being Created
&lt;/h3&gt;

&lt;p&gt;A missing lead isn't always a lost submission. Some CRMs detect an existing contact or lead and block a new record from being created.&lt;/p&gt;

&lt;p&gt;This can happen when someone submits a demo request using an email address already in the CRM. Depending on the duplicate rules, the system may reject the new record, update an existing contact, or flag the submission for review. The behavior varies by CRM configuration.&lt;/p&gt;

&lt;p&gt;Check the duplicate handling rules and search for the submitted email address across both contacts and leads. The person may already exist, even if the sales team doesn't see a new lead in the expected view.&lt;/p&gt;

&lt;p&gt;For example, Salesforce documents cases where duplicate rules prevent website form submissions from creating new lead records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Cite&lt;/span&gt; &lt;span class="na"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;turn878168search0&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;turn878168search2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. CRM Workflows Change or Redirect the Record
&lt;/h3&gt;

&lt;p&gt;Sometimes the CRM receives the submission, but the lead ends up somewhere the team isn't looking.&lt;/p&gt;

&lt;p&gt;Assignment rules may send it to another sales representative. Automation may change its status, associate it with an existing contact, or move it into a different queue. Filters and permissions can also make a record difficult to find.&lt;/p&gt;

&lt;p&gt;Search the CRM using the email address from your test submission, then check the record's creation time, owner, status, and activity history. Review any automation triggered when a new lead arrives.&lt;/p&gt;

&lt;p&gt;If the record exists but doesn't appear in the expected dashboard or lead list, investigate the CRM's views, filters, and assignment rules before changing the website integration.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Analytics Counts a Conversion That the CRM Never Receives
&lt;/h3&gt;

&lt;p&gt;Analytics and CRM records measure different things. An analytics event can fire when a visitor clicks a submit button or reaches a confirmation page, even if the integration fails later.&lt;/p&gt;

&lt;p&gt;This can inflate reported conversions and make campaign performance difficult to assess. A campaign might appear to generate plenty of leads while sales receives fewer contacts than expected.&lt;/p&gt;

&lt;p&gt;Review the event configuration to understand exactly what triggers a conversion. Where possible, track confirmed submission success separately from the initial button click, and compare those events with actual CRM records.&lt;/p&gt;

&lt;p&gt;Be careful with the numbers: one person may submit a form more than once, and a CRM may update an existing contact without creating a new lead. Those cases can explain differences between the totals without indicating a technical failure.&lt;/p&gt;


&lt;h2&gt;
  
  
  How to Fix Lead Tracking Issues From Form to CRM
&lt;/h2&gt;

&lt;p&gt;Once you understand the possible failure points, the next step is to follow a test submission through the actual systems. This helps you identify where the data stops moving, instead of guessing which tool is responsible.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Submit a Test Lead
&lt;/h3&gt;

&lt;p&gt;Use a controlled test with a unique email address and realistic values for the required fields. Record the time of submission, the page URL, and the information entered.&lt;/p&gt;

&lt;p&gt;If the form captures campaign details, check whether the relevant UTM parameters or hidden fields are included. Avoid using real customer information in test records.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Confirm That the Website Received the Submission
&lt;/h3&gt;

&lt;p&gt;Check the form platform, server logs, or browser developer tools, depending on how the form works. Look for the submission request and its response.&lt;/p&gt;

&lt;p&gt;A successful response confirms only what that specific endpoint is designed to confirm. If the website sends data to an intermediate service, you still need to verify the next step.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Check the Integration or API Response
&lt;/h3&gt;

&lt;p&gt;Follow the request that transfers the form data to the CRM. Look for authentication failures, invalid field values, missing required data, rate limits, and server errors.&lt;/p&gt;

&lt;p&gt;If the integration uses webhooks or an automation platform, review its execution history. Check whether the workflow ran, whether each action succeeded, and whether an error message explains the failure.&lt;/p&gt;

&lt;p&gt;For custom integrations, make sure logs contain enough information to diagnose failures without exposing passwords, access tokens, or unnecessary personal data.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4: Search the CRM for the Test Record
&lt;/h3&gt;

&lt;p&gt;Search for the test email across the relevant contact and lead records. Check for existing records, duplicate handling, assignment rules, and automation that may have changed the record after submission.&lt;/p&gt;

&lt;p&gt;If the CRM rejected the request, use the available error details to identify the field or rule that caused the problem. For example, Microsoft's documentation on &lt;a href="https://learn.microsoft.com/en-us/troubleshoot/dynamics-365/customer-insights/journeys/forms/troubleshooting-forms" rel="noopener noreferrer"&gt;troubleshooting failed marketing form submissions&lt;/a&gt; explains how submission logs can help identify failures when records cannot be created or updated.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5: Repeat the Test After Fixing the Cause
&lt;/h3&gt;

&lt;p&gt;Once you've corrected the issue, submit another test and follow the same path. Confirm that the CRM creates or updates the expected record, the relevant fields contain the right values, and the lead appears in the correct place.&lt;/p&gt;

&lt;p&gt;Also verify that analytics records the intended conversion. If the fix involves resubmitting failed submissions, check for duplicates before replaying them, since some systems may create another record when a submission is processed again.&lt;/p&gt;


&lt;h2&gt;
  
  
  How to Prevent Missing Leads From Becoming a Recurring Problem
&lt;/h2&gt;

&lt;p&gt;Finding one missing lead is useful. Making sure the same problem doesn't quietly affect the next campaign is even more important.&lt;/p&gt;

&lt;p&gt;A reliable setup combines routine testing, clear ownership, useful error logs, and regular checks between form submissions and CRM records.&lt;/p&gt;
&lt;h3&gt;
  
  
  Test Forms After Important Website Changes to Verify Lead Tracking
&lt;/h3&gt;

&lt;p&gt;A form can break after a website release, a CMS update, a CRM field change, or an integration adjustment. Add form testing to the release process whenever a change could affect submission behavior.&lt;/p&gt;

&lt;p&gt;Test the full journey, including the confirmation message, CRM record creation, required fields, lead assignment, and conversion tracking. A form that looks correct on the page still needs to pass data through every connected system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Monitor Lead Tracking Errors and Failed Submissions
&lt;/h3&gt;

&lt;p&gt;Make sure someone can see when a form integration fails. Depending on the platform, this could involve error notifications, automation logs, API monitoring, or alerts for failed workflow runs.&lt;/p&gt;

&lt;p&gt;Choose a process that fits the site's complexity. A small site may only need regular checks and clear error notifications, while a larger marketing operation may benefit from automated monitoring and alerts.&lt;/p&gt;

&lt;p&gt;The important part is to make failures visible. If the team discovers missing leads only after sales reports a problem, the website may have been losing opportunities for days.&lt;/p&gt;
&lt;h3&gt;
  
  
  Compare Form Submissions With CRM Records to Verify Lead Tracking
&lt;/h3&gt;

&lt;p&gt;Review form submissions and CRM records on a regular schedule. Look for unexpected gaps, sudden changes in conversion counts, and forms that generate submissions but few usable contacts.&lt;/p&gt;

&lt;p&gt;Compare equivalent measures wherever possible. Account for repeat submissions, updates to existing contacts, spam filtering, and differences in how each platform counts conversions.&lt;/p&gt;

&lt;p&gt;Give the process a clear owner. Marketing may own campaign reporting, while engineering or a WebOps lead monitors the integrations and investigates technical failures. Both teams should know who responds when the numbers stop matching.&lt;/p&gt;
&lt;h3&gt;
  
  
  Keep Changes to Forms and Integrations Documented
&lt;/h3&gt;

&lt;p&gt;Record important changes to form fields, CRM mappings, API connections, validation rules, and automation. When a problem appears, the team can check what changed and narrow down the cause more quickly.&lt;/p&gt;

&lt;p&gt;This is a practical part of website operations: the forms, analytics, and integrations that support marketing need ongoing care, just like the pages visitors see.&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;/p&gt;
  Why does my website form say submitted, but the lead doesn't appear in my CRM?
  &lt;br&gt;
A successful form message confirms that a specific step has completed, but it doesn't always mean the CRM saved the lead. The integration may have failed, the CRM may have rejected the data, or duplicate rules may have prevented a new record. Check the submission logs, integration response, and CRM records to identify where the process stopped.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  How can I check whether my website form is connected to my CRM correctly?
  &lt;br&gt;
Submit a test lead using a unique email address, then follow it through the form handler, integration, and CRM. Confirm that the request succeeds, the required fields map correctly, and the expected record appears in the CRM. Also check assignment rules and automation to make sure the record reaches the right place.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  Can Google Analytics track a lead that never reaches the CRM?
  &lt;br&gt;
Yes. Analytics can record a conversion when a visitor clicks a submit button or reaches a confirmation page, even if a later integration request fails. To improve lead tracking, define what counts as a successful conversion and compare analytics events with CRM records. Remember that repeat submissions and updates to existing contacts can also cause differences in the totals.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  What are the most common causes of missing leads in a CRM?
  &lt;br&gt;
Common causes include failed API requests, expired credentials, incorrect field mappings, missing required values, duplicate rules, and CRM automation that changes or redirects records. Reporting filters and permissions can also make a lead difficult to find. Checking each stage of the form-to-CRM process helps narrow down the cause.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  How can B2B SaaS teams prevent leads from disappearing?
  &lt;br&gt;
B2B SaaS teams can reduce missing leads by testing forms after relevant website changes, monitoring integration errors, checking CRM field mappings, and comparing form activity with CRM records. Clear ownership also matters: marketing, sales, and engineering should know who monitors the process and who investigates when submissions fail.&lt;br&gt;


&lt;p&gt;&lt;/p&gt;


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

&lt;p&gt;A form can look healthy on the website while the process behind it quietly loses leads. That's why reliable lead tracking needs more than a confirmation message or a conversion event. The full journey, from the visitor's submission to the CRM record, needs to work as expected.&lt;/p&gt;

&lt;p&gt;When a lead goes missing, trace one test submission through each system, inspect the logs, and confirm what happened inside the CRM. Once you find the cause, add the right checks and monitoring so the same problem doesn't go unnoticed during the next campaign.&lt;/p&gt;

&lt;p&gt;For B2B SaaS teams, this is an important part of WebOps. The website, forms, analytics, and CRM integrations all support the path from marketing activity to sales conversations. Keeping those connections healthy helps teams make better decisions and gives sales a more reliable stream of leads.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>performance</category>
      <category>marketing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Top 5 Open Source LLM Gateways</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Mon, 26 Oct 2026 09:13:16 +0000</pubDate>
      <link>https://dev.to/hadil/top-5-open-source-llm-gateways-29g3</link>
      <guid>https://dev.to/hadil/top-5-open-source-llm-gateways-29g3</guid>
      <description>&lt;p&gt;When an application uses AI models from multiple providers, having a good open source LLM gateway can make a huge difference in how applications perform.&lt;/p&gt;

&lt;p&gt;An LLM gateway gives applications a central way to manage model requests, handle provider-specific integrations, and apply routing and usage policies without spreading that logic across the codebase.&lt;/p&gt;

&lt;p&gt;For engineering teams, open source offers greater control over the infrastructure handling AI traffic. Teams can inspect the code, configure the gateway to meet their application requirements, and integrate it with their existing systems.&lt;/p&gt;

&lt;p&gt;This, however, leads to another problem: self-hosted solutions involve some operational issues as well, including updates, monitoring, availability, and security.&lt;/p&gt;

&lt;p&gt;In this article, we will compare &lt;strong&gt;five LLM gateways&lt;/strong&gt; worth considering: Bifrost, LiteLLM, Kong, Apache APISIX, and Agent Router.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The best open source LLM gateway depends on how much control your team needs over model routing, infrastructure, and production AI traffic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://getmax.im/bifrosty" rel="noopener noreferrer"&gt;Bifrost&lt;/a&gt;&lt;/strong&gt;: An open source AI gateway built for production workloads, with a focus on low-overhead request handling, model routing, reliability, observability, and centralized governance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.litellm.ai/" rel="noopener noreferrer"&gt;LiteLLM&lt;/a&gt;&lt;/strong&gt;: A Python-based open source gateway with broad model-provider support and an OpenAI-compatible interface, making it useful for applications that need flexible integrations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://konghq.com/" rel="noopener noreferrer"&gt;Kong&lt;/a&gt;&lt;/strong&gt;: An API management platform with AI gateway capabilities, suited to organizations that want to manage AI traffic alongside their broader API infrastructure. Open source availability depends on the specific Kong components and features being evaluated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://apisix.apache.org/" rel="noopener noreferrer"&gt;Apache APISIX&lt;/a&gt;&lt;/strong&gt;: An Apache 2.0-licensed open source API gateway with AI gateway plugins for proxying LLM requests, balancing traffic across providers, and applying token-based rate limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://theagentrouter.ai/" rel="noopener noreferrer"&gt;Agent Router&lt;/a&gt;&lt;/strong&gt;: An open source AI gateway built on Envoy that provides a unified API for hosted models, self-hosted inference, and MCP servers, with centralized routing, credentials, quotas, and failover.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful starting point is to compare each gateway's license, deployment model, provider compatibility, routing capabilities, and operational requirements. Those details can tell you more about its fit for production.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an LLM Gateway, and Why Does It Matter in Production?
&lt;/h2&gt;

&lt;p&gt;An LLM gateway is a layer between your application and the large language models (LLMs) it uses. It provides a common entry point for sending requests to AI providers and managing how those requests are processed.&lt;/p&gt;

&lt;p&gt;Without a gateway, an application might need separate integrations for OpenAI, Anthropic, Google, AWS Bedrock, and self-hosted models. Each integration can introduce its own authentication, request formats, error handling, and usage-tracking logic. As the number of providers grows, maintaining those differences becomes an ongoing engineering task.&lt;/p&gt;

&lt;p&gt;Depending on the platform and configuration, an LLM gateway can provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified APIs:&lt;/strong&gt; Connect to multiple model providers through a consistent interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model routing:&lt;/strong&gt; Direct requests to different models based on application requirements or configured rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries and failover:&lt;/strong&gt; Handle certain provider errors and redirect requests when a configured fallback is available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability:&lt;/strong&gt; Track request volume, latency, errors, token usage, and other operational metrics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost management:&lt;/strong&gt; Monitor spending and apply budgets or rate limits where supported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and access control:&lt;/strong&gt; Manage provider credentials, application access, and policies around AI traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment flexibility:&lt;/strong&gt; Run the gateway in your own infrastructure or use a managed offering, depending on the platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An open source LLM gateway gives engineering teams an additional advantage: the ability to inspect and customize the available code, subject to its license. Self-hosting can also help organizations control where gateway processing takes place, although the actual data path depends on which model providers they use.&lt;/p&gt;

&lt;p&gt;Open source does not automatically mean that every enterprise feature is free or that the gateway requires no maintenance. Licensing, commercial editions, deployment requirements, and the work involved in operating the service all deserve attention before choosing a platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  How We Evaluated These LLM Gateways
&lt;/h2&gt;

&lt;p&gt;This comparison looks at how each gateway fits into a real development environment, with attention to both its technical capabilities and its open source model.&lt;/p&gt;

&lt;p&gt;The main evaluation criteria are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open source status and licensing:&lt;/strong&gt; Which components are available under an open source license, and which capabilities may require a commercial edition?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider compatibility:&lt;/strong&gt; How easily can developers connect hosted APIs and self-hosted models?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing and reliability:&lt;/strong&gt; What options are available for retries, fallback behavior, and distributing requests?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability and governance:&lt;/strong&gt; How can teams monitor AI usage and control access or spending?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment and integration:&lt;/strong&gt; How well does the gateway fit existing application stacks and infrastructure?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Comparison: Top 5 Open Source LLM Gateways
&lt;/h2&gt;

&lt;p&gt;The table below summarizes the five gateways and highlights the differences developers should investigate before adopting one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;LLM Gateway&lt;/th&gt;
&lt;th&gt;Core Technology / Approach&lt;/th&gt;
&lt;th&gt;Open Source Scope&lt;/th&gt;
&lt;th&gt;Key Strength&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bifrost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go-based gateway&lt;/td&gt;
&lt;td&gt;Apache 2.0 core&lt;/td&gt;
&lt;td&gt;Performance and centralized AI traffic control&lt;/td&gt;
&lt;td&gt;Production AI infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LiteLLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python SDK and proxy&lt;/td&gt;
&lt;td&gt;MIT-licensed open source core&lt;/td&gt;
&lt;td&gt;Broad provider compatibility&lt;/td&gt;
&lt;td&gt;Multi-provider applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kong&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kong Gateway and AI plugins&lt;/td&gt;
&lt;td&gt;Open source gateway; AI features vary by edition&lt;/td&gt;
&lt;td&gt;API management and AI traffic policies&lt;/td&gt;
&lt;td&gt;Teams using Kong infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Apache APISIX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Extensible API gateway with AI plugins&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;td&gt;LLM proxying, provider load balancing, and token-based rate limiting&lt;/td&gt;
&lt;td&gt;Teams wanting open source API and AI traffic management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent Router&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Envoy-based gateway&lt;/td&gt;
&lt;td&gt;Apache 2.0&lt;/td&gt;
&lt;td&gt;Cloud-native AI traffic management&lt;/td&gt;
&lt;td&gt;Kubernetes and platform engineering teams&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Licensing note: “Open source” can refer to a gateway core, selected plugins, or a specific repository, not necessarily every feature offered by the company.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Bifrost (by Maxim AI)
&lt;/h2&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%2Fyw7kwvqf5p4ds2w55zuz.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%2Fyw7kwvqf5p4ds2w55zuz.png" alt="Screenshot of the Bifrost homepage hero section" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bifrost is an &lt;a href="https://getmax.im/github/bifrost" rel="noopener noreferrer"&gt;open source&lt;/a&gt; LLM gateway designed for engineering teams building production AI applications. Written in Go, it provides a unified API for routing requests across model providers while helping teams manage performance, reliability, observability, and access to AI services from a central layer.&lt;/p&gt;

&lt;p&gt;Bifrost's OpenAI-compatible API lets developers connect existing applications through familiar client libraries, with less provider-specific integration work. It also supports governance for MCP tool calls and agent-related traffic, extending its role beyond conventional model requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance, Routing, and Reliability
&lt;/h3&gt;

&lt;p&gt;Bifrost provides configurable routing policies for distributing requests and handling provider failures in production environments. According to its &lt;a href="https://docs.getbifrost.ai/overview" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;, Bifrost adds &lt;strong&gt;11 µs&lt;/strong&gt; of overhead per request at &lt;strong&gt;5,000&lt;/strong&gt; requests per second (RPS) in sustained benchmarks. This gives engineering teams a documented performance reference when evaluating gateway overhead for high-throughput AI applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability, Cost, and Governance
&lt;/h3&gt;

&lt;p&gt;Bifrost includes built-in observability and OpenTelemetry-compatible metrics and tracing. Its virtual keys let teams apply budgets and rate limits, helping them manage usage across applications and consumers. Semantic caching can also reduce repeated model calls when requests are suitable for reuse.&lt;/p&gt;

&lt;p&gt;Additional capabilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usage attribution: Associate AI consumption with the relevant keys or consumers.&lt;/li&gt;
&lt;li&gt;Monitoring integrations: Export telemetry for analysis alongside existing observability systems.&lt;/li&gt;
&lt;li&gt;Request efficiency: Apply semantic caching where repeated requests are suitable for reuse.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bifrost also provides capabilities for managing MCP tool access and agent-related traffic. Its Enterprise features include guardrails, role-based access control (RBAC), identity-provider integrations such as single sign-on (SSO), and audit logs. These capabilities are part of the Enterprise offering, while the open source core includes features such as virtual keys, budgets, rate limits, routing, and observability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment and Open Source Flexibility
&lt;/h3&gt;

&lt;p&gt;Bifrost's open source core is licensed under Apache 2.0 and can be self-hosted using options such as Docker, Kubernetes, or its Go binary. This gives engineering teams flexibility to integrate the gateway into their existing infrastructure and deployment workflows.&lt;/p&gt;

&lt;p&gt;Self-hosting gives teams control over the gateway's configuration and operating environment. However, requests sent to external model providers remain subject to those providers' data-handling practices.&lt;/p&gt;

&lt;p&gt;Bifrost Enterprise supports deployment options for organizations with stricter infrastructure requirements, including in-VPC, on-premises, and air-gapped environments. These deployment options are part of the Enterprise offering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Bifrost offers a free, self-hosted open source version. Teams can deploy it using supported installation methods without paying for the core gateway itself.&lt;/p&gt;

&lt;p&gt;The enterprise offering has custom pricing and adds capabilities for organizations with more advanced security, governance, and deployment requirements. Teams should confirm which features are included in each tier before making a decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Bifrost is best for engineering and platform teams running production AI workloads that need low gateway overhead, centralized request management, and visibility into AI usage. Its support for model requests, MCP tools, and agent traffic also makes it relevant to teams building more complex AI systems.&lt;/p&gt;

&lt;p&gt;Teams with strict security and infrastructure requirements can evaluate the enterprise offering for advanced governance and deployment options. For smaller applications with limited routing or operational needs, a simpler gateway may be sufficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getmax.im/bifrosty" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Bifrost&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  2. LiteLLM
&lt;/h2&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%2Frc6n2y361bdapmc2c03a.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%2Frc6n2y361bdapmc2c03a.png" alt="Screenshot of the LiteLLM homepage hero section" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LiteLLM is an &lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;open source&lt;/a&gt; LLM gateway and Python SDK that gives developers a consistent way to work with different language model providers. Its gateway exposes an OpenAI-compatible API, helping applications connect to models from providers such as OpenAI, Anthropic, and AWS Bedrock without maintaining a separate request integration for each one.&lt;/p&gt;

&lt;p&gt;LiteLLM is useful for teams that expect their model choices to change over time or need to support several providers across different applications. Its open source gateway includes features such as routing, retries, fallbacks, usage tracking, and virtual keys, while the Python SDK lets developers call supported models through a common interface.&lt;/p&gt;

&lt;p&gt;The project is MIT-licensed, and the gateway can be self-hosted. Teams can also evaluate its commercial offering when they need additional enterprise governance, security features, or support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;LiteLLM's open source gateway is free to self-host, with infrastructure and model-provider charges remaining the team's responsibility. Its Enterprise offering uses annual pricing based on factors such as request capacity, deployment architecture, and support requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;LiteLLM is best for developers and platform teams that need broad model-provider compatibility through an open source LLM gateway. Its unified API, Python SDK, and usage-management features make it a practical option for applications that need flexibility across providers without duplicating integration code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.litellm.ai/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore LiteLLM&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Kong
&lt;/h2&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%2F7kq8qtxac4tg81cbyxcf.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%2F7kq8qtxac4tg81cbyxcf.png" alt="Screenshot of the Kong AI Gateway homepage hero section" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kong brings AI traffic management into Kong's broader API connectivity platform. It helps organizations manage requests to language models alongside existing APIs, with capabilities for routing, access control, observability, and AI-specific policies.&lt;/p&gt;

&lt;p&gt;For engineering teams already using Kong, this approach can reduce the need to introduce a completely separate system for AI traffic. The platform supports LLM requests and also includes capabilities for MCP and agent-to-agent (A2A) traffic, helping teams manage interactions across AI applications and their supporting services.&lt;/p&gt;

&lt;p&gt;One important distinction is its licensing and deployment model. Kong offers an &lt;a href="https://github.com/kong/kong" rel="noopener noreferrer"&gt;open source&lt;/a&gt; gateway, but not every AI Gateway feature is necessarily available under the same open source terms. Some capabilities are tied to Kong Konnect or commercial offerings, while fully self-hosted AI gateway deployments may require an enterprise offering. Teams should confirm the specific components and policies they intend to use before selecting Kong as an open source solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Kong's pricing depends on the selected platform, deployment model, and feature set. Its Konnect AI Management Plus plan is listed from $25 per month plus usage, while enterprise plans use custom pricing. Additional AI gateway capabilities and fully self-hosted enterprise deployments may have separate costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Kong is best for organizations that want to integrate AI traffic management with an established API gateway platform. It is worth considering when API policies, identity, traffic governance, and existing Kong infrastructure are central to the team's architecture. However, teams specifically seeking a fully open source LLM gateway should carefully verify which AI features can be used under their chosen license and deployment model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://konghq.com/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Kong&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Apache APISIX
&lt;/h2&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%2Fs2toxzn7uvxtv68amjvf.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%2Fs2toxzn7uvxtv68amjvf.png" alt="Screenshot of the Apache APISIX AI Gateway homepage" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apache APISIX is an &lt;a href="https://github.com/apache/apisix" rel="noopener noreferrer"&gt;open source&lt;/a&gt; API gateway licensed under Apache 2.0 and maintained by the Apache Software Foundation. Its AI gateway capabilities are provided through open source plugins that let teams route requests to supported LLM providers and OpenAI-compatible endpoints. This makes APISIX relevant to teams that want to manage API and AI traffic through the same gateway.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ai-proxy&lt;/code&gt; plugin forwards requests to supported model providers, including OpenAI, Anthropic, Gemini, Amazon Bedrock, and other compatible endpoints. For applications that need to distribute requests across model instances, &lt;code&gt;ai-proxy-multi&lt;/code&gt; adds load balancing, retries, fallbacks, and health checks. The &lt;code&gt;ai-rate-limiting&lt;/code&gt; plugin can enforce usage limits based on token consumption.&lt;/p&gt;

&lt;p&gt;APISIX also offers AI-focused capabilities such as prompt templates, prompt decoration, prompt guard, retrieval-augmented generation (RAG), and request logging through its plugin ecosystem. Teams should review each plugin's documentation to confirm supported providers, configuration requirements, and limitations for their intended workload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Apache APISIX is available under the Apache 2.0 open source license, with no software license fee for the open source project itself. Teams running a self-hosted deployment are responsible for infrastructure, operations, and any costs charged by the model providers or external services they use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Apache APISIX is best for platform and infrastructure teams that want to manage AI requests alongside their existing API traffic. Its open source AI plugins make it worth considering for teams that need LLM proxying, provider load balancing, retries, fallbacks, and token-based rate limits without relying on a separate commercial AI gateway edition.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apisix.apache.org/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Apache APISIX&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Agent Router
&lt;/h2&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%2F6gu8y8wk8e61xa8bmkdg.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%2F6gu8y8wk8e61xa8bmkdg.png" alt="Screenshot of the Agent Router homepage hero section" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agent Router is an &lt;a href="https://github.com/theagentrouter/agent-router" rel="noopener noreferrer"&gt;open source&lt;/a&gt; gateway for managing AI and agent traffic, built on Envoy and Envoy Gateway. Formerly known as Envoy AI Gateway, the project provides a consistent, OpenAI-compatible API for connecting applications to hosted model providers, self-hosted inference services, and MCP servers. It is now an Agentic AI Foundation project and retains its Apache 2.0 license.&lt;/p&gt;

&lt;p&gt;Agent Router is designed with cloud-native infrastructure in mind. It gives platform teams a central place to manage credentials, routing, quotas, and failover, while Envoy handles the underlying traffic flow. Its support for Kubernetes-based deployments and multiple AI providers makes it an option for organizations that want AI gateway capabilities integrated with their existing networking and infrastructure practices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Agent Router is an open source project available under the Apache 2.0 license, so there is no software license fee for using the project itself. Teams deploying it in their own infrastructure still need to account for hosting, maintenance, and any fees charged by the model providers they connect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Agent Router is best for platform engineering teams building cloud-native AI infrastructure, especially those already using Envoy or Kubernetes. Its architecture is a good fit for teams that want centralized access control and routing across hosted models, self-hosted inference, and AI tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theagentrouter.ai/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Agent Router&lt;/a&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Choose the Right LLM Gateway
&lt;/h2&gt;

&lt;p&gt;Choosing an LLM gateway comes down to how your application uses AI today and what your team expects to manage as it grows. A gateway with extensive features may be unnecessary for a small application, while a basic proxy can become limiting when several services, providers, and engineering teams depend on it.&lt;/p&gt;

&lt;p&gt;Here are the main factors to consider before choosing an open source LLM gateway.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Which model providers do I need to support?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check whether the gateway supports the providers and models your application uses, including any self-hosted inference services. An OpenAI-compatible API can simplify integration, but compatibility does not guarantee that every provider-specific feature behaves identically.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How important are performance and reliability?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For applications serving real users, gateway overhead, provider latency, and failure handling can all affect the experience. Look at how the gateway handles retries, fallback models, load balancing, and high availability. Test realistic traffic patterns before relying on published performance figures to estimate your own results.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Do I need an open source gateway or a commercial platform?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open source software gives your team the opportunity to inspect the code, customize supported behavior, and manage its deployment. However, review the exact license and confirm which features are included in the open source release. Some platforms reserve advanced governance, support, or deployment capabilities for paid plans.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How will I monitor usage and control costs?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As more applications start using LLMs, tracking requests and spending becomes harder without a central view. Look for usage reporting, request tracing, budgets, rate limits, and cost information that helps you understand which applications or teams consume the most resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Where does the gateway need to run?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider whether your application requires a managed service, a self-hosted deployment, Kubernetes integration, private networking, or an isolated environment. Self-hosting gives your team more control over the gateway's deployment, but it also means taking responsibility for upgrades, security, monitoring, and availability.&lt;/p&gt;

&lt;p&gt;The right choice depends on how these requirements fit together. Compare the gateway's licensing, operational workload, provider compatibility, and production capabilities before committing to one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is an open source LLM gateway?
&lt;/h3&gt;

&lt;p&gt;→ An open source LLM gateway is software that sits between an application and the language models it uses. It provides a central interface for sending model requests and can handle tasks such as provider routing, authentication, retries, monitoring, and usage limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does an LLM gateway work?
&lt;/h3&gt;

&lt;p&gt;→ An LLM gateway receives a request from an application, determines which configured model or provider should handle it, and forwards the request with the required authentication and parameters. It then returns the provider's response to the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is an open source LLM gateway free to use?
&lt;/h3&gt;

&lt;p&gt;→ An open source LLM gateway can be free to download and use under its license, but running it still has costs. Teams may need to pay for servers, databases, monitoring infrastructure, maintenance, and the models they call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can an LLM gateway connect to multiple AI providers?
&lt;/h3&gt;

&lt;p&gt;→ Yes. Supporting multiple providers is one of the main reasons developers use an LLM gateway. A unified interface can reduce the need to maintain separate integrations for each provider and make it easier to change models as application requirements evolve. However, API compatibility does not guarantee identical behavior across models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does an LLM gateway improve AI application security?
&lt;/h3&gt;

&lt;p&gt;→ An LLM gateway can strengthen security by centralizing provider credentials, controlling access, applying rate limits, and recording requests for monitoring and auditing. Depending on the implementation, it may also support budgets, guardrails, and policies that restrict how applications use AI services.&lt;/p&gt;




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

&lt;p&gt;Open source LLM gateways give developers a practical way to manage model integrations, routing, and operational controls as AI applications grow.&lt;/p&gt;

&lt;p&gt;The right choice depends on the providers you use, the infrastructure you operate, and the level of control your team needs over production AI traffic.&lt;/p&gt;

&lt;p&gt;Among the five options covered here, Bifrost is a strong candidate for teams prioritizing production performance, centralized routing, and control over AI infrastructure. &lt;/p&gt;

&lt;p&gt;LiteLLM is worth evaluating when broad provider compatibility and its Python SDK are important. &lt;/p&gt;

&lt;p&gt;Kong makes sense for organizations already invested in its API management ecosystem, while Apache APISIX offers open source AI plugins for LLM proxying, provider load balancing, and token-based rate limiting. Agent Router is worth considering for teams building AI infrastructure around Envoy and cloud-native networking.&lt;/p&gt;

&lt;p&gt;Before making a decision, verify each project's current license, inspect which features are available in its open source version, and consider the operational work required to run it reliably. Provider coverage and feature lists matter, but so do maintainability, security updates, and how well the gateway fits your existing architecture.&lt;/p&gt;

&lt;p&gt;Teams evaluating LLM gateways can &lt;a href="https://getmaxim.ai/bifrost/book-a-demo" rel="noopener noreferrer"&gt;request a Bifrost demo&lt;/a&gt; or &lt;a href="https://getmax.im/github/bifrost" rel="noopener noreferrer"&gt;review the open source repository&lt;/a&gt;.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>ai</category>
      <category>llm</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Best Open Source React Calendar Libraries for Scheduling in 2026</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:32:26 +0000</pubDate>
      <link>https://dev.to/hadil/best-open-source-react-calendar-libraries-for-scheduling-in-2026-4h11</link>
      <guid>https://dev.to/hadil/best-open-source-react-calendar-libraries-for-scheduling-in-2026-4h11</guid>
      <description>&lt;p&gt;The best open source React calendar libraries depend on what you're building. The need for a simple date picker within a booking form is naturally quite distinct than that of a team calendar application that allows the users to drag and drop events to manage their schedule.&lt;/p&gt;

&lt;p&gt;This matters a lot because the React calendar components cater to various needs. While date pickers are designed for selecting a particular date or a range, event calendars display scheduled events and let users create, edit, or move them. Scheduling components go further with features such as recurring events, timeline views, resource allocation, and timezone handling.&lt;/p&gt;

&lt;p&gt;Whether you are creating a project management application or an employee booking platform, the chances are that you will need more than just a date picker. The right calendar component is one that can match your needs with regard to the intended actions that the users may perform.&lt;/p&gt;

&lt;p&gt;This guide compares six open source React calendar libraries for 2026: FullCalendar, React Big Calendar, SVAR React Calendar, Schedule-X, DayPilot Lite, and MUI X Scheduler. Each offers a different balance of functionality, customization, developer experience, and paid features in their commercial tiers.&lt;/p&gt;

&lt;p&gt;The aim is to choose the right library for your software application.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If you're looking for the best open source React calendar libraries in 2026, the right choice depends on whether you need a simple event calendar or advanced features such as recurring events and resource management. &lt;/p&gt;

&lt;p&gt;Here’s a quick overview of the six libraries covered in this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://fullcalendar.io/" rel="noopener noreferrer"&gt;FullCalendar&lt;/a&gt;:&lt;/strong&gt; A mature, feature-rich calendar with multiple views, extensive customization, and premium options for advanced scheduling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://bigcalendar.github.io/react-big-calendar/" rel="noopener noreferrer"&gt;React Big Calendar&lt;/a&gt;:&lt;/strong&gt; A MIT-licensed React calendar with familiar day, week, month, and agenda views, ideal for developers who want control over their implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://svar.dev/react/calendar/" rel="noopener noreferrer"&gt;SVAR React Calendar&lt;/a&gt;:&lt;/strong&gt; A customizable React calendar with built-in event editing, drag-and-drop, and REST integration, plus advanced scheduling features in its PRO edition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://schedule-x.dev/" rel="noopener noreferrer"&gt;Schedule-X&lt;/a&gt;:&lt;/strong&gt; A modern, modular calendar with framework integrations and a plugin-based approach to additional functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://javascript.daypilot.org/open-source/" rel="noopener noreferrer"&gt;DayPilot Lite&lt;/a&gt;:&lt;/strong&gt; A practical option for appointment booking, staff scheduling, and resource calendars, with an Apache 2.0-licensed edition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://mui.com/x/react-scheduler/" rel="noopener noreferrer"&gt;MUI X Scheduler&lt;/a&gt;:&lt;/strong&gt; A React scheduling component with Material UI theming, event interactions, and additional capabilities available through its Premium edition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All six are worth evaluating, but check each library’s licensing and feature availability before choosing it for a commercial project.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Choose an Open Source React Calendar Library
&lt;/h2&gt;

&lt;p&gt;Before comparing individual libraries, let's identify which calendar features your application needs. &lt;/p&gt;

&lt;p&gt;A library with dozens of views and scheduling options can be useful for a complex application, but it may introduce unnecessary complexity if you only need a weekly event calendar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core calendar features
&lt;/h3&gt;

&lt;p&gt;Start with the views and interactions your users will need most often.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day, week, and month views: These cover common scheduling workflows, although some applications also need an agenda or list view.&lt;/li&gt;
&lt;li&gt;Event management: Check whether users can create, edit, and delete events, and whether the library provides built-in editing forms or requires you to build your own.&lt;/li&gt;
&lt;li&gt;Drag-and-drop and resizing: These interactions make it easier to reschedule meetings and adjust event durations.&lt;/li&gt;
&lt;li&gt;Multiple calendars and event grouping: Useful when users manage several teams, projects, appointment types, or personal calendars.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced scheduling capabilities
&lt;/h3&gt;

&lt;p&gt;More demanding applications need to consider how events behave over time and how the calendar handles larger datasets.&lt;/p&gt;

&lt;p&gt;Recurring events, timezone support, resource-based scheduling, and timeline views can become essential for applications managing staff shifts, meeting rooms, equipment, or appointments across locations. &lt;/p&gt;

&lt;p&gt;Dynamic data loading is also worth evaluating when a calendar needs to fetch events as users navigate between dates or when the dataset grows.&lt;/p&gt;

&lt;p&gt;I also recommend checking which features are available in the open source edition. Some libraries provide a capable free calendar while reserving advanced scheduling views or other functionality for a paid tier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer experience and integration
&lt;/h3&gt;

&lt;p&gt;A calendar can look impressive in a demo but still require considerable work to integrate into a real application. Check the quality of its React API, TypeScript support, documentation, customization options, and event-handling model.&lt;/p&gt;

&lt;p&gt;You'll also need to understand how the component connects to your backend. Does it accept your existing event data? &lt;br&gt;
Can you respond to edits and persist them through your API? &lt;br&gt;
Does it support custom styling without extensive overrides?&lt;/p&gt;

&lt;p&gt;Finally, consider maintenance and licensing. A MIT-licensed library, a commercial product with a free edition, and a beta component can all be reasonable choices, but they carry different trade-offs for production applications.&lt;/p&gt;

&lt;p&gt;Now, let's look at six options and how they fit different scheduling requirements.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. FullCalendar
&lt;/h2&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%2Fydl0kdmxe06jvembkrfj.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%2Fydl0kdmxe06jvembkrfj.png" alt="Screenshot of the FullCalendar homepage hero section introducing its interactive JavaScript event calendar and available calendar views." width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fullcalendar/fullcalendar" rel="noopener noreferrer"&gt;FullCalendar&lt;/a&gt; is one of the established options for developers who need an interactive event calendar in a web application. It supports familiar calendar views, event rendering, navigation, and a range of customization options. Its &lt;a href="https://fullcalendar.io/docs/react" rel="noopener noreferrer"&gt;official React integration&lt;/a&gt; makes it possible to configure the calendar through React props and customize event content with JSX.&lt;/p&gt;

&lt;p&gt;Its modular architecture is useful when you want to add calendar views as needed. You can start with a month view, introduce a weekly schedule, and add interaction features as your application grows.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;This example uses FullCalendar v7, where the standard calendar views are imported from the React package's subpaths. The v7 package structure differs from v6, so use the matching installation command and imports.&lt;/p&gt;

&lt;p&gt;Install the dependencies:&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; @fullcalendar/react temporal-polyfill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a basic calendar component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;FullCalendar&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;@fullcalendar/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;classicThemePlugin&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;@fullcalendar/react/themes/classic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dayGridPlugin&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;@fullcalendar/react/daygrid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fullcalendar/react/skeleton.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fullcalendar/react/themes/classic/theme.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@fullcalendar/react/themes/classic/palette.css&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;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02&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;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Design review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-05&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TeamCalendar&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FullCalendar&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;classicThemePlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dayGridPlugin&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;initialView&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dayGridMonth"&lt;/span&gt;
      &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;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 gives you a month calendar populated with two events. You can add more views and interactions through the relevant plugins and configuration options.&lt;/p&gt;

&lt;p&gt;Explore the &lt;a href="https://fullcalendar.io/demos" rel="noopener noreferrer"&gt;live demos&lt;/a&gt; to see the calendar in action.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multiple calendar views: Month, week, day, and list-style views are available through the relevant plugins.&lt;/li&gt;
&lt;li&gt;Event interactions: Event selection, dragging, and resizing can be configured for supported views.&lt;/li&gt;
&lt;li&gt;Custom event rendering: React components and JSX let you control how event titles, times, and other details appear.&lt;/li&gt;
&lt;li&gt;External data: Events can be supplied as arrays or loaded through supported event sources.&lt;/li&gt;
&lt;li&gt;Framework integrations: FullCalendar provides integrations for React, Vue, Angular, Preact, and other environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;The main consideration is the distinction between Standard and Premium. The Standard packages are MIT-licensed and work well for many everyday calendar requirements. Advanced resource views and timeline functionality belong to Premium, which has separate licensing terms.&lt;/p&gt;

&lt;p&gt;That matters if you're building a commercial scheduling product. Before committing, identify which views you need and confirm whether they are included in the edition you plan to use.&lt;/p&gt;

&lt;p&gt;FullCalendar also has a broad configuration surface. This is useful for complex applications, although teams building a simple calendar may need time to understand its plugin system and available options.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;FullCalendar is a good fit for applications that need a mature, configurable calendar with multiple views, event interactions, and a wide range of integration options. It's worth considering when your requirements are well defined and you're comfortable checking the licensing of any Premium features you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fullcalendar.io/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore FullCalendar&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  2. React Big Calendar
&lt;/h2&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%2Fe313cptzjv85t7p7szb1.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%2Fe313cptzjv85t7p7szb1.png" alt="Screenshot of the React Big Calendar project homepage showing its React event-calendar component and links to its documentation and demo." width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bigcalendar/react-big-calendar" rel="noopener noreferrer"&gt;React Big Calendar&lt;/a&gt; is an event calendar built specifically for React. Its layout will feel familiar to anyone who has used a calendar application such as Google Calendar or Outlook. It focuses on displaying events across day, week, month, and agenda views, with a flexible data model that lets you connect your own event objects to the calendar.&lt;/p&gt;

&lt;p&gt;One of its strengths is that the library stays close to the calendar UI itself. You provide the events, define how their start and end dates are represented, and customize the presentation to suit your application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Install the library and a date localizer. This example uses Day.js:&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;react-big-calendar dayjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create a component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;Calendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dayjsLocalizer&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;react-big-calendar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dayjs&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;dayjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-big-calendar/lib/css/react-big-calendar.css&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;localizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dayjsLocalizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dayjs&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;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;11&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client meeting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&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="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TeamCalendar&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Calendar&lt;/span&gt;
        &lt;span class="na"&gt;localizer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;localizer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;startAccessor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"start"&lt;/span&gt;
        &lt;span class="na"&gt;endAccessor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
        &lt;span class="na"&gt;titleAccessor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;
        &lt;span class="na"&gt;defaultView&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"week"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;The &lt;code&gt;localizer&lt;/code&gt; handles date formatting and calendar-related date operations. The &lt;code&gt;startAccessor&lt;/code&gt; and &lt;code&gt;endAccessor&lt;/code&gt; tell the component which fields to read from each event. Notice the container's explicit height: React Big Calendar needs a defined height for its calendar layout to display correctly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Familiar calendar views: Day, week, month, and agenda layouts cover common scheduling workflows.&lt;/li&gt;
&lt;li&gt;Flexible event data: Accessor properties let you map the calendar to your application's existing event structure.&lt;/li&gt;
&lt;li&gt;Date localization: Integrations with libraries such as Day.js, date-fns, and Moment support date formatting and localization.&lt;/li&gt;
&lt;li&gt;Custom styling: CSS and Sass variables provide control over colors, spacing, and other visual details.&lt;/li&gt;
&lt;li&gt;Drag-and-drop support: An optional add-on supports moving and resizing events, with additional setup required.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;React Big Calendar is a good option for traditional event-calendar interfaces, but you'll need to evaluate how much of the surrounding scheduling experience your application requires.&lt;/p&gt;

&lt;p&gt;The core component doesn't automatically provide a complete booking workflow with backend persistence, business rules, or a ready-made event editor. Those pieces usually need to be implemented in your application. Drag-and-drop also requires configuring its add-on and handling the resulting event changes.&lt;/p&gt;

&lt;p&gt;Styling deserves attention, too. The library includes standard CSS and Sass customization options, but extensive overrides can affect the layout, so custom themes should be tested across the calendar's different views.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;React Big Calendar works well for React applications that need a conventional calendar UI, flexible event data, and control over the surrounding experience. It's a sensible choice for internal dashboards, team calendars, and scheduling interfaces where your team is happy to implement its own event forms and application-specific logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bigcalendar.github.io/react-big-calendar/?path=/docs/about-big-calendar--docs" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore React Big Calendar&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  3. SVAR React Calendar
&lt;/h2&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%2Fyk9i8a4skhuc7ucsqa5j.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%2Fyk9i8a4skhuc7ucsqa5j.png" alt="Screenshot of the SVAR React Calendar homepage hero section introducing its React event-calendar component, scheduling features, and live demo." width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/svar-widgets/react-calendar/" rel="noopener noreferrer"&gt;SVAR React Calendar&lt;/a&gt; is a React calendar library that integrates natively into React applications that need more than a basic date grid. It provides calendar views, event interactions, and built-in editing capabilities, making it worth considering for scheduling interfaces in SaaS products, internal dashboards, and business applications.&lt;/p&gt;

&lt;p&gt;A useful aspect of SVAR is its approach to event management. Developers can display events, let users move them with drag-and-drop, and edit details through a built-in form with rich text and file attachments. That gives you a starting point for an interactive scheduling experience without building every calendar interaction from scratch.&lt;/p&gt;

&lt;p&gt;The library also offers a separate PRO edition for applications that need more advanced scheduling features, including editable recurring events, timezone support, dynamic loading, and export to PDF, PNG, and Excel. Teams can start with the MIT-licensed core and adopt additional functionality as their requirements grow. The exact edition you need depends on which views and scheduling capabilities your application requires.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Install the React Calendar 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; @svar-ui/react-calendar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can then render a calendar with a small collection of events:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;Calendar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Willow&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;@svar-ui/react-calendar&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;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&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;span class="na"&gt;id&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="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client meeting&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TeamCalendar&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Willow&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Calendar&lt;/span&gt; &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Willow&lt;/span&gt;&lt;span class="p"&gt;&amp;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;The &lt;code&gt;Willow&lt;/code&gt; wrapper supplies the CSS variables the calendar needs for its default styling. The &lt;code&gt;date&lt;/code&gt; prop sets the initially displayed date, while each event uses a unique &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;start&lt;/code&gt;, and &lt;code&gt;end&lt;/code&gt; value, along with a &lt;code&gt;text&lt;/code&gt; label for its title. The event dates must be JavaScript &lt;code&gt;Date&lt;/code&gt; objects; ISO date strings won't render correctly in this example.&lt;/p&gt;

&lt;p&gt;Before using the snippet in a production application, verify the exact event schema and component API against the &lt;a href="https://docs.svar.dev/react/calendar/getting-started/quick-start/" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;, especially if you're working with a different package version.&lt;/p&gt;

&lt;p&gt;Explore the &lt;a href="https://svar.dev/react/calendar/#demo" rel="noopener noreferrer"&gt;live demo&lt;/a&gt; to see the calendar in action.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Day, week, and month views with event interactions: The open source component supports core calendar workflows, including displaying events, moving them through drag-and-drop, and editing event details with its built-in form.&lt;/li&gt;
&lt;li&gt;Calendar grouping and event filtering: Applications that manage multiple teams, event types, or schedules can use grouping and filtering capabilities to help users find the information relevant to them.&lt;/li&gt;
&lt;li&gt;React and TypeScript integration: The component is built for React and supports TypeScript-based development, making it a natural candidate for projects that already use typed event models and reusable React components.&lt;/li&gt;
&lt;li&gt;Backend integration: SVAR provides a &lt;code&gt;RestDataProvider&lt;/code&gt; for connecting calendar data to a server. This helps developers integrate event loading and persistence into applications that use REST APIs.&lt;/li&gt;
&lt;li&gt;Customization and theming: CSS-variable-based theming allows developers to adapt the calendar's appearance to their application's visual design.&lt;/li&gt;
&lt;li&gt;Advanced scheduling through PRO: The separate PRO edition adds capabilities such as recurring events, dynamic data loading, timezone support, and Timeline, Agenda, Year, and Resource views.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For implementation details, check the &lt;a href="https://docs.svar.dev/react/calendar/advanced-features/saving-to-server/" rel="noopener noreferrer"&gt;server integration&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;SVAR's free edition covers the core calendar experience, including Day, Week, and Month views, event editing, drag-and-drop, theming, and backend wiring. However, recurring events, Timeline, Agenda, Year, and Resource views, as well as dynamic loading and timezone projection support, are part of the commercial PRO edition.&lt;/p&gt;

&lt;p&gt;That matters if you're comparing free React calendar libraries for a production application. You can build a useful scheduling interface with the MIT edition, but you'll need to budget for PRO if your requirements include those advanced capabilities.&lt;/p&gt;

&lt;p&gt;The backend helper also doesn't remove the need for application-level engineering. You'll still need to configure your endpoints, handle permissions, validate event changes, and make sure the server's scheduling rules are enforced.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;SVAR React Calendar is a good choice for developers who want a customizable event calendar with built-in editing, drag-and-drop, and a straightforward React integration. It's especially worth evaluating if you expect your scheduling requirements to grow and want the option of adding recurring events, resource scheduling, or timeline views later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://svar.dev/react/calendar/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore SVAR React Calendar&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Schedule-X
&lt;/h2&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%2Frmni1vq7odn7181rqvn9.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%2Frmni1vq7odn7181rqvn9.png" alt="Screenshot of the Schedule-X homepage hero section introducing its JavaScript event calendar, modern interface, and framework integrations." width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/schedule-x/schedule-x" rel="noopener noreferrer"&gt;Schedule-X&lt;/a&gt; is a calendar library designed around a clean interface, modular configuration, and framework integrations. It supports common calendar views and lets developers extend the core experience with plugins when their applications need additional behavior.&lt;/p&gt;

&lt;p&gt;Schedule-X has a plugin-based approach. The basic calendar can handle event display and navigation, while capabilities such as drag-and-drop may require separate premium plugins. That gives developers control over which features they add, but it also means you need to check the licensing and setup requirements for each plugin before choosing it.&lt;/p&gt;

&lt;p&gt;Schedule-X provides &lt;a href="https://schedule-x.dev/docs/calendar" rel="noopener noreferrer"&gt;integration guides&lt;/a&gt; for React, Vue, Angular, Svelte, and Preact, which make an option for teams working across different frontend frameworks.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Install the calendar, its default theme, and the required Temporal polyfill:&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; @schedule-x/react @schedule-x/calendar @schedule-x/theme-default temporal-polyfill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A basic React integration looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useCalendarApp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ScheduleXCalendar&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;@schedule-x/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;createViewDay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createViewWeek&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createViewMonthGrid&lt;/span&gt;&lt;span class="p"&gt;,&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;@schedule-x/calendar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;temporal-polyfill/global&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@schedule-x/theme-default/dist/index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TeamCalendar&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;calendar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCalendarApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selectedDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nf"&gt;createViewDay&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nf"&gt;createViewWeek&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nf"&gt;createViewMonthGrid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;events&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;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02 10:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02 11:00&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;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client meeting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-04 14:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-04 15:00&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;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ScheduleXCalendar&lt;/span&gt; &lt;span class="na"&gt;calendarApp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;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 uses Schedule-X's React integration. The &lt;code&gt;useCalendarApp&lt;/code&gt; hook configures the calendar, while &lt;code&gt;ScheduleXCalendar&lt;/code&gt; renders it in the component tree. The selected date, available views, and event data are passed into the calendar configuration, and the Temporal polyfill is imported as required by the current setup.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multiple calendar views: Schedule-X supports calendar layouts for different ways of planning and reviewing events. The views you enable depend on your configuration and installed packages.&lt;/li&gt;
&lt;li&gt;Modular plugins: You can extend the calendar with additional functionality when your project needs it.&lt;/li&gt;
&lt;li&gt;Custom event presentation: Event properties and styling options let you adapt the calendar to your application's visual design.&lt;/li&gt;
&lt;li&gt;Framework integrations: Official guides cover React, Vue, Angular, Svelte, and Preact.&lt;/li&gt;
&lt;li&gt;Event interaction: The library supports event-related interactions, although you should check whether a specific interaction comes with the core package or requires a premium plugin.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;The main consideration is feature availability across the core library and its plugins. For example, Schedule-X's drag-and-drop plugin is a premium add-on that requires an active license. If moving events directly on the calendar is essential to your application, include that cost in your evaluation.&lt;/p&gt;

&lt;p&gt;The setup also differs from a typical React component that you render directly in JSX. Schedule-X creates a calendar instance and renders it into a DOM element, so you'll need to manage its lifecycle carefully when integrating it with React.&lt;/p&gt;

&lt;p&gt;This approach can work well, but developers should evaluate the library's configuration model, plugin requirements, and licensing before committing to it for a larger application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;Schedule-X is worth considering if you want a modern-looking calendar, prefer modular functionality, and need integrations across frontend frameworks. It may be a good fit for teams that are comfortable managing a calendar instance and selecting plugins according to their requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://schedule-x.dev/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore Schedule-X&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  5. DayPilot Lite
&lt;/h2&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%2Fu0lt6rpfmv1n8q029bri.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%2Fu0lt6rpfmv1n8q029bri.png" alt="Screenshot of the DayPilot open-source homepage hero section introducing its JavaScript calendar and Scheduler components for event and resource scheduling." width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/DayPilotCode/daypilot-javascript-scheduler-open-source" rel="noopener noreferrer"&gt;DayPilot Lite&lt;/a&gt; is a JavaScript library for building interactive calendars and scheduling interfaces. Its components include a day/week Calendar, a monthly calendar, a resource Scheduler with a horizontal timeline, and a date Navigator. It's useful for applications that need more than a basic calendar, including appointment booking, room reservations, staff scheduling, and equipment management.&lt;/p&gt;

&lt;p&gt;DayPilot supports plain JavaScript and TypeScript, with framework-specific packages for React, Angular, and Vue. Its Lite edition is released under the Apache 2.0, which permits use in personal and commercial projects. DayPilot also offers a commercial Pro edition, so developers should check the feature matrix to confirm which edition includes the functionality their application requires.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;For a plain JavaScript project, install the open-source 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; @daypilot/daypilot-lite-javascript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create an HTML element to host the calendar:&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;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"calendar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then initialize the calendar and provide a few events:&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;DayPilot&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;@daypilot/daypilot-lite-javascript&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;calendar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DayPilot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Calendar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calendar&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="na"&gt;viewType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Week&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;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&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;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02T10:00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-02T11:00:00&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;span class="na"&gt;id&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client meeting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-04T14:00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-11-04T15:00:00&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;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;events&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 initializes DayPilot Lite's JavaScript Calendar in week view and loads two events. The &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; values define each event's scheduled time, while &lt;code&gt;text&lt;/code&gt; provides the label displayed on the calendar. The same Lite package also includes separate Scheduler, Month, and Navigator components.&lt;/p&gt;

&lt;p&gt;Explore the &lt;a href="https://javascript.daypilot.org/demo/lite/" rel="noopener noreferrer"&gt;live demos&lt;/a&gt; to see the calendar in action.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multiple calendar components: Choose from day and week calendars, a monthly view, a resource calendar, and a date navigator.&lt;/li&gt;
&lt;li&gt;Drag-and-drop scheduling: Users can create, move, resize, and copy events directly on the calendar.&lt;/li&gt;
&lt;li&gt;Resource management: Display people, rooms, equipment, or other resources as columns in a calendar or rows on a horizontal timeline in the Scheduler.&lt;/li&gt;
&lt;li&gt;Custom styling: Adjust event appearance, calendar cells, headers, business hours, and themes to match the application's interface.&lt;/li&gt;
&lt;li&gt;Scheduling controls: Support read-only modes, locked events, disabled time slots, and overlap handling through event configuration and handlers.&lt;/li&gt;
&lt;li&gt;Framework support: Use DayPilot Lite in JavaScript, TypeScript, React, Angular, or Vue projects, with TypeScript definitions and downloadable examples available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;DayPilot Lite is a scheduling component library, not a complete booking backend. Your application still needs to handle data persistence, authentication, permissions, and any server-side availability rules. Some advanced capabilities are exclusive to DayPilot Pro.&lt;/p&gt;

&lt;p&gt;There is also a distinction worth noting for React developers: DayPilot provides a dedicated React package, but its core offering is a set of calendar and scheduling components available across several frameworks. Teams looking for a React-only calendar API may prefer a library designed specifically around React conventions.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;DayPilot Lite is good for developers building appointment booking, staff or equipment scheduling, resource calendars, and other applications that need interactive calendar components across JavaScript frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javascript.daypilot.org/open-source/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore DayPilot Lite&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  6. MUI X Scheduler
&lt;/h2&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%2F0ypjipj1rs36bjl7zh09.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%2F0ypjipj1rs36bjl7zh09.png" alt="Screenshot of the MUI X Scheduler homepage hero section introducing its React event-calendar component and scheduling capabilities." width="799" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mui/mui-x" rel="noopener noreferrer"&gt;MUI X Scheduler&lt;/a&gt; is part of the MUI X family of React components. It provides event-calendar functionality for applications that need interactive scheduling within a React-based interface.&lt;/p&gt;

&lt;p&gt;For teams already using Material UI, this is a natural option to evaluate because it follows the same broader design-system approach. You can use familiar theming tools and integrate the scheduler into an application that already relies on MUI components.&lt;/p&gt;

&lt;p&gt;The current offering includes a Community event calendar under the MIT license and a Premium edition with additional scheduling capabilities. The Community edition includes multiple views, resource support, drag-and-drop, resizing, and theming. Premium adds features such as recurring events, exception dates, lazy loading through data sources, and an event timeline.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Install the Community scheduler package and its Material UI dependencies:&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; @mui/x-scheduler @mui/material @emotion/react @emotion/styled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;MUI X Scheduler's API can evolve, so use the current quick-start documentation for the exact component exports and event types. A basic integration follows this pattern:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useState&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;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;EventCalendar&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;@mui/x-scheduler/event-calendar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;SchedulerEvent&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;@mui/x-scheduler/models&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;initialEvents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SchedulerEvent&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sprint planning&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="mi"&gt;11&lt;/span&gt;&lt;span class="p"&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="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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Client meeting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;end&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&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="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TeamCalendar&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEvents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SchedulerEvent&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;initialEvents&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EventCalendar&lt;/span&gt;
        &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onEventsChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setEvents&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;defaultVisibleDate&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&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="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;The &lt;code&gt;EventCalendar&lt;/code&gt; component receives a typed event array and reports event changes through &lt;code&gt;onEventsChange&lt;/code&gt;, allowing React state to stay in sync with user edits. The container needs a defined height so the calendar has room to render. The example uses the Community package; confirm the current feature and licensing boundaries before relying on Premium functionality.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multiple calendar views: Display schedules in different calendar layouts to suit your application's workflow.&lt;/li&gt;
&lt;li&gt;Drag-and-drop and resizing: Let users reschedule events and adjust their durations through direct interactions.&lt;/li&gt;
&lt;li&gt;Resource support: Organize schedules around resources, such as people or rooms.&lt;/li&gt;
&lt;li&gt;Material UI theming: Customize the scheduler to match the rest of a Material UI application.&lt;/li&gt;
&lt;li&gt;Recurring events and data sources: Premium adds recurrence handling, exception dates, and lazy loading through data sources.&lt;/li&gt;
&lt;li&gt;Event Timeline: Premium provides a horizontal timeline for visualizing allocations across resources and date ranges.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Limitations and trade-offs
&lt;/h3&gt;

&lt;p&gt;The main consideration is the commercial feature boundary. The Community package offers useful scheduling functionality, but recurring events, data-source lazy loading, and the Event Timeline require the Premium edition. Check the current licensing and feature matrix before making those features part of your product requirements.&lt;/p&gt;

&lt;p&gt;MUI X Scheduler is also a good fit for applications that already use React and, especially, Material UI. If your application has a completely different design system, you'll want to assess the effort required to adapt its appearance and component behavior.&lt;/p&gt;

&lt;p&gt;Finally, scheduling components can evolve quickly. Since the Scheduler is a relatively new addition to the MUI X ecosystem, review its current API, documentation, and release status before choosing it for a long-lived production project.&lt;/p&gt;
&lt;h3&gt;
  
  
  Best for
&lt;/h3&gt;

&lt;p&gt;MUI X Scheduler is worth evaluating for React applications that use Material UI and need a customizable event calendar with built-in scheduling interactions. Its Community edition may cover everyday needs, while Premium is relevant when recurring events, dynamic loading, or timeline-based resource planning become essential.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mui.com/x/react-scheduler/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Explore MUI X Scheduler&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  React calendar libraries compared
&lt;/h2&gt;

&lt;p&gt;The six libraries cover overlapping use cases, but their approaches to licensing, integration, and advanced scheduling differ. &lt;/p&gt;

&lt;p&gt;Use this table as a shortlist, then verify the specific features you need against the official documentation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Key advantages&lt;/th&gt;
&lt;th&gt;License&lt;/th&gt;
&lt;th&gt;Framework integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FullCalendar&lt;/td&gt;
&lt;td&gt;Feature-rich event calendars&lt;/td&gt;
&lt;td&gt;Multiple views, React integration, extensive customization&lt;/td&gt;
&lt;td&gt;MIT for standard features; Premium features require a commercial license&lt;/td&gt;
&lt;td&gt;React, Vue, Angular, Preact, and others&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Big Calendar&lt;/td&gt;
&lt;td&gt;Traditional React event calendars&lt;/td&gt;
&lt;td&gt;Familiar layouts, flexible event data, customizable styling&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;Native React&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVAR React Calendar&lt;/td&gt;
&lt;td&gt;Interactive React calendars with built-in editing&lt;/td&gt;
&lt;td&gt;Drag-and-drop, event editor, filtering, REST integration&lt;/td&gt;
&lt;td&gt;MIT core; PRO commercial&lt;/td&gt;
&lt;td&gt;Native React, also available for Svelte &amp;amp; Vue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedule-X&lt;/td&gt;
&lt;td&gt;Modern, modular event calendars&lt;/td&gt;
&lt;td&gt;Framework integrations, customizable views, plugin-based functionality&lt;/td&gt;
&lt;td&gt;MIT core; certain premium plugins require a license&lt;/td&gt;
&lt;td&gt;React, Vue, Angular, Svelte, Preact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DayPilot Lite&lt;/td&gt;
&lt;td&gt;Appointment booking and resource scheduling&lt;/td&gt;
&lt;td&gt;Day/week calendar, monthly calendar, resource Scheduler, date Navigator&lt;/td&gt;
&lt;td&gt;Apache 2.0 for Lite; Pro commercial&lt;/td&gt;
&lt;td&gt;JavaScript, TypeScript, React, Angular, Vue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MUI X Scheduler (beta)&lt;/td&gt;
&lt;td&gt;React applications needing an event calendar&lt;/td&gt;
&lt;td&gt;Multiple views, resource support, drag-and-drop, Material UI integration&lt;/td&gt;
&lt;td&gt;MIT Community; Premium commercial&lt;/td&gt;
&lt;td&gt;Native React&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A note on licensing: "Open source" doesn't automatically mean every feature is free. FullCalendar, SVAR, Schedule-X, DayPilot Lite, and MUI X have different boundaries around paid functionality. Check the license of the specific package or plugin you intend to use, particularly if the application is commercial.&lt;/p&gt;


&lt;h2&gt;
  
  
  Quick recommendations: Which React calendar library should you choose?
&lt;/h2&gt;

&lt;p&gt;If you've narrowed your options down to two or three libraries, these recommendations can help you make the final decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need a mature calendar ecosystem, extensive view options, and flexible integrations, and you're comfortable with its Premium licensing model for advanced scheduling → &lt;strong&gt;Choose FullCalendar&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If you want a straightforward, MIT-licensed React event calendar and are happy to build your own event editor and backend integration → &lt;strong&gt;Choose React Big Calendar&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If you want a customizable React calendar with built-in event editing, drag-and-drop, and REST data integration, plus the option to add recurring events, dynamic loading, and advanced scheduling views through PRO → &lt;strong&gt;Choose SVAR React Calendar&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If you prefer a modern interface and a modular approach to calendar functionality, and its core features and plugin licensing meet your needs → &lt;strong&gt;Choose Schedule-X&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If you're building appointment booking, staff scheduling, or resource calendars and want an Apache 2.0-licensed starting point → &lt;strong&gt;Choose DayPilot Lite&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If your application already uses Material UI and you want an event calendar that fits its design system, with a Premium upgrade path for more advanced scheduling → &lt;strong&gt;Choose MUI X Scheduler&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no universal winner among these open source React calendar libraries. The right choice depends on the complexity of your data, the design system you're using, and the features your budget can support.&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What are the best open source React calendar libraries in 2026?
&lt;/h3&gt;

&lt;p&gt;→ Some of the best open source React calendar libraries to evaluate in 2026 are FullCalendar, React Big Calendar, SVAR React Calendar, Schedule-X, DayPilot Lite, and MUI X Scheduler Community. They offer different combinations of calendar views, event interactions, customization, and licensing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Which React calendar library supports drag-and-drop event scheduling?
&lt;/h3&gt;

&lt;p&gt;→ FullCalendar, React Big Calendar with its drag-and-drop add-on, SVAR React Calendar, DayPilot Lite, and MUI X Scheduler Community offer drag-and-drop functionality, although setup and feature availability differ. Schedule-X also offers drag-and-drop through its relevant plugin.&lt;/p&gt;
&lt;h3&gt;
  
  
  Which open source React calendar library is best for booking applications?
&lt;/h3&gt;

&lt;p&gt;→ For booking applications, DayPilot Lite is worth considering for appointment and resource scheduling, while SVAR React Calendar can suit applications that need interactive events, built-in editing, and backend integration. FullCalendar is another option for flexible event-based interfaces. Remember that the calendar component handles the interface; your application still needs booking validation, availability checks, conflict prevention, and server-side persistence.&lt;/p&gt;
&lt;h3&gt;
  
  
  Are there free React calendar libraries for commercial projects?
&lt;/h3&gt;

&lt;p&gt;→ Yes. React Big Calendar is MIT-licensed, SVAR React Calendar's core is MIT-licensed, DayPilot Lite uses Apache 2.0, and FullCalendar's standard React package is MIT-licensed. Schedule-X's core is MIT-licensed, although some plugins require a paid license. MUI X Scheduler Community is also MIT-licensed, with advanced features available under its commercial Premium license.&lt;/p&gt;
&lt;h3&gt;
  
  
  What should I look for when choosing a React scheduling component?
&lt;/h3&gt;

&lt;p&gt;→ Start with the calendar views you need, then check event creation and editing, drag-and-drop, resizing, recurring events, timezone support, resource scheduling, and backend integration. Also evaluate TypeScript support, customization, documentation, performance, and licensing. For an accurate comparison of open source React calendar libraries, test the features your application needs instead of choosing based on the number of features advertised.&lt;/p&gt;


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

&lt;p&gt;Choosing a React calendar library is not just about finding a component that displays dates and events. The library also needs to support the way your users schedule work, interact with appointments, and manage changes throughout the day.&lt;/p&gt;

&lt;p&gt;Before settling on any of React calendar libraries, build a small proof of concept using realistic event data. Test how users create and edit appointments, how the calendar handles overlapping events, and how changes are saved to your backend. If you need recurring events, timezone handling, or resource allocation, verify those features in the exact edition you plan to use.&lt;/p&gt;

&lt;p&gt;A calendar that looks good in a demo is a useful starting point. A calendar that fits your application's data model and real scheduling workflows is the one worth shipping.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
      <category>css</category>
    </item>
    <item>
      <title>Where Do Your Users' Passwords Actually Live? Self-Hosted vs Managed Keycloak</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Wed, 21 Oct 2026 09:06:20 +0000</pubDate>
      <link>https://dev.to/hadil/where-do-your-users-passwords-actually-live-self-hosted-vs-managed-keycloak-97e</link>
      <guid>https://dev.to/hadil/where-do-your-users-passwords-actually-live-self-hosted-vs-managed-keycloak-97e</guid>
      <description>&lt;p&gt;Choosing between self-hosted and managed Keycloak affects more than where your identity service runs. It determines who maintains the infrastructure, who handles security updates, and how much responsibility your team takes on when users need to authenticate.&lt;/p&gt;

&lt;p&gt;When you add authentication to an application, it's easy to focus on the login screen. You choose between passwords and passkeys, connect an identity provider, and make sure users can access their accounts. But there's another question worth asking before your application goes live: &lt;strong&gt;where are your users' credentials stored, and who is responsible for protecting them?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keycloak gives developers control over authentication and identity management. You can run it on infrastructure you manage, or use a managed Keycloak service that takes care of much of the underlying operation.&lt;/p&gt;

&lt;p&gt;Both approaches can work well. The right choice depends on your security requirements, your team's infrastructure experience, your budget, and how much operational responsibility you're prepared to take on.&lt;/p&gt;

&lt;p&gt;Let's look at what happens to user passwords in each setup, what changes when you choose a managed service, and how to decide which option makes sense for your application.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;self-hosted Keycloak&lt;/strong&gt;, user credentials are stored in the Keycloak database that you configure and operate. Your team is responsible for securing that database, maintaining backups, applying updates, and protecting the infrastructure.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;&lt;a href="https://skycloak.io/" rel="noopener noreferrer"&gt;Skycloak&lt;/a&gt;'s managed Keycloak&lt;/strong&gt;, you use the official upstream Keycloak platform without operating the underlying identity infrastructure yourself. Skycloak manages the infrastructure and provides automatic updates, while your team retains control over Keycloak configuration and remains responsible for integrating authentication securely into your application.&lt;/p&gt;

&lt;p&gt;Here's the practical difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted Keycloak:&lt;/strong&gt; You control the deployment, database, network, updates, backups, and access policies. You also carry the operational burden of keeping everything secure and available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Keycloak with Skycloak:&lt;/strong&gt; Skycloak manages the underlying infrastructure while giving your team full Keycloak admin access. All plans support unlimited users, so pricing isn't tied to monthly active users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regions and portability:&lt;/strong&gt; Skycloak offers deployment regions in the US, EU, Canada, and Australia, plus realm export options to help you plan a migration if you later choose to self-host.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Getting started:&lt;/strong&gt; You can try Skycloak free for 21 days without providing a credit card.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password security:&lt;/strong&gt; Keycloak stores passwords as salted password hashes, not as readable plaintext passwords. Database access, configuration, backups, and administrative permissions still need protection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; Self-hosting can offer more infrastructure control, but server costs are only part of the total expense. Managed services add a service fee but can reduce the engineering time spent operating the identity platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The short answer:&lt;/strong&gt; In a standard deployment, Keycloak handles authentication in both models. The main difference is who operates the identity infrastructure and how responsibilities are divided between your team and the provider. If you use an external user store, credential storage and verification may be handled partly or entirely by that system.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Happens to a Password in Keycloak?
&lt;/h2&gt;

&lt;p&gt;Imagine someone creates an account in your application. They enter an email address, choose a password, and click Create account. Where does that password go?&lt;/p&gt;

&lt;p&gt;In a typical Keycloak setup using its built-in user storage, Keycloak receives the password during account creation and stores a password hash in its configured database. A password hash is the output of a one-way password-hashing function. When the user signs in later, Keycloak verifies the submitted password against the stored hash. If an external user store handles authentication, credential storage and verification may follow a different process.&lt;/p&gt;

&lt;p&gt;The database doesn't need to contain the original password in readable form. Keycloak uses a password-hashing algorithm and configuration designed to make guessing passwords computationally expensive. The exact algorithm and parameters depend on the Keycloak version and configuration.&lt;/p&gt;

&lt;p&gt;Keycloak's default password-hashing algorithm depends on the version and deployment configuration. Keycloak 24 changed the default from &lt;code&gt;pbkdf2-sha256&lt;/code&gt; to &lt;code&gt;pbkdf2-sha512&lt;/code&gt;. Starting with Keycloak 25, Argon2 became the default for non-FIPS deployments, while FIPS deployments use a compatible algorithm such as &lt;code&gt;pbkdf2-sha512&lt;/code&gt;. Existing credentials may retain their previous hash until the user next signs in and Keycloak re-hashes the password under the current configuration.&lt;/p&gt;

&lt;p&gt;To inspect or configure password policy settings, open the Keycloak Admin Console and navigate to &lt;strong&gt;Authentication → Policies → Password policy&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Review the policy configured for your realm before assuming it matches the defaults for a particular release.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Keycloak Stores Password Credentials
&lt;/h3&gt;

&lt;p&gt;In a standard Keycloak deployment using its built-in user storage, password credentials are stored in the database configured for Keycloak. The &lt;code&gt;CREDENTIAL&lt;/code&gt; table holds credential records associated with users, including password-related data and metadata.&lt;/p&gt;

&lt;p&gt;Two fields help illustrate how that works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SECRET_DATA&lt;/code&gt;: stores sensitive credential data, including password-hashing information.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CREDENTIAL_DATA&lt;/code&gt;: stores additional credential metadata, such as information about the credential type and its configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fields contain structured data, not a readable copy of the user's original password. The exact contents depend on the credential type and Keycloak version.&lt;/p&gt;

&lt;p&gt;For example, a password credential record may contain data resembling the following. These are illustrative examples, not actual values from a live Keycloak database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;SECRET_DATA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;illustrative&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[password hash omitted]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"salt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[salt omitted]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"additionalParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;CREDENTIAL_DATA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;illustrative&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;example&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"algorithm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"argon2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hashIterations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[configured value]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"additionalParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The exact field names and structure can vary by Keycloak version and credential implementation.&lt;/p&gt;
&lt;h3&gt;
  
  
  Password Hashing Isn't the Whole Security Story
&lt;/h3&gt;

&lt;p&gt;This distinction matters because password hashing and database security solve different problems. Hashing helps protect passwords if someone obtains a copy of the credential records, but it doesn't make a compromised identity server or database harmless. Attackers who gain administrative access may be able to alter accounts, change authentication settings, or access other sensitive information.&lt;/p&gt;

&lt;p&gt;For example, your deployment still needs to protect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database access and administrative credentials.&lt;/li&gt;
&lt;li&gt;Backups containing credential records and other sensitive data.&lt;/li&gt;
&lt;li&gt;Keycloak configuration and privileged administrative accounts.&lt;/li&gt;
&lt;li&gt;The infrastructure and network surrounding the identity service.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Where Is the Rest of the Identity Data Stored?
&lt;/h3&gt;

&lt;p&gt;Your Keycloak deployment also holds information beyond password credentials, including user profiles, groups, roles, and configuration data. Depending on your setup, it may connect to external identity providers or use additional user-storage systems. The exact location of user data therefore depends on how the realm and user storage are configured.&lt;/p&gt;

&lt;p&gt;For a standard deployment using Keycloak's built-in user storage, the password hashes are held in the configured database. If your environment uses an external user store, the credentials may be managed there instead.&lt;/p&gt;

&lt;p&gt;This is the starting point for comparing self-hosted and managed Keycloak: the credential-handling model can remain the same, while the people responsible for the surrounding infrastructure change.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Self-Hosted Keycloak Means
&lt;/h2&gt;

&lt;p&gt;With self-hosted Keycloak, you deploy and operate the identity service on infrastructure under your team's control. That might be a virtual machine, a container platform, Kubernetes, or another supported environment.&lt;/p&gt;

&lt;p&gt;You choose the deployment architecture, configure the database, manage network access, and decide how the service fits into your existing infrastructure. This gives you considerable flexibility, which can be valuable when an application has specific compliance requirements or needs to integrate with internal systems.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Your Team Is Responsible For
&lt;/h3&gt;

&lt;p&gt;The trade-off is that your team must take responsibility for operating the service reliably.&lt;/p&gt;

&lt;p&gt;That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Applying Keycloak security updates and testing upgrades.&lt;/li&gt;
&lt;li&gt;Maintaining the database and testing backups and restores.&lt;/li&gt;
&lt;li&gt;Monitoring availability and planning for service failures.&lt;/li&gt;
&lt;li&gt;Protecting administrative accounts, TLS certificates, and network rules.&lt;/li&gt;
&lt;li&gt;Reviewing configuration changes and tracking security advisories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's also the less visible work: testing recovery procedures and making sure they still work when you need them.&lt;/p&gt;
&lt;h3&gt;
  
  
  When Does Self-Hosting Make Sense?
&lt;/h3&gt;

&lt;p&gt;Self-hosting can be a good fit when you need deep infrastructure control and have the people and processes to maintain it. It can also make sense when your organization already operates identity infrastructure and has established procedures for security, monitoring, and incident response.&lt;/p&gt;

&lt;p&gt;But running Keycloak yourself doesn't automatically make your authentication more secure. The result depends on how well the service, database, network, and operational processes are configured and maintained.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Changes With Managed Keycloak?
&lt;/h2&gt;

&lt;p&gt;Managed Keycloak shifts much of the infrastructure work to a service provider. You still use Keycloak for identity management and authentication, but the provider operates the managed environment according to its service offering.&lt;/p&gt;

&lt;p&gt;For a development team, that can mean less time spent maintaining servers, planning upgrades, monitoring infrastructure, and managing database operations. It can also make it easier to get an identity service running without first building an entire deployment and maintenance process.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the Provider May Manage
&lt;/h3&gt;

&lt;p&gt;The provider may manage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure provisioning and maintenance.&lt;/li&gt;
&lt;li&gt;Database operations and backups.&lt;/li&gt;
&lt;li&gt;Keycloak updates and upgrades.&lt;/li&gt;
&lt;li&gt;Availability monitoring and infrastructure recovery.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  What Still Belongs to Your Team?
&lt;/h3&gt;

&lt;p&gt;However, managed Keycloak doesn't mean someone else automatically handles every aspect of authentication security.&lt;/p&gt;

&lt;p&gt;Your team still needs to configure authentication flows, manage realm settings, assign appropriate roles, protect administrative access, and integrate the identity provider correctly with your application. You also need to decide how users are onboarded, how accounts are recovered, and what permissions they receive after signing in.&lt;/p&gt;

&lt;p&gt;Data ownership and access deserve attention, too. Before choosing a provider, understand where your identity data is stored, who can access it, how backups are protected, and what happens when you decide to leave the service.&lt;/p&gt;

&lt;p&gt;Managed Keycloak is useful when you want to use Keycloak's identity capabilities without taking on the full burden of operating the infrastructure.&lt;/p&gt;


&lt;h2&gt;
  
  
  Self-Hosted Keycloak vs Skycloak: A Practical Comparison
&lt;/h2&gt;

&lt;p&gt;Both deployment models can use Keycloak's authentication features. The differences become clearer when you compare the responsibilities involved in running them.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Self-hosted Keycloak&lt;/th&gt;
&lt;th&gt;Skycloak&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;Your team provisions and operates it&lt;/td&gt;
&lt;td&gt;Skycloak manages the underlying infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database operations&lt;/td&gt;
&lt;td&gt;Your team configures, secures, and maintains the database&lt;/td&gt;
&lt;td&gt;Skycloak manages the underlying infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security updates&lt;/td&gt;
&lt;td&gt;Your team plans, tests, and applies updates&lt;/td&gt;
&lt;td&gt;Automatic updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backups and recovery&lt;/td&gt;
&lt;td&gt;Your team configures and tests backup and restore procedures&lt;/td&gt;
&lt;td&gt;Skycloak manages infrastructure, updates, backups, and scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Availability&lt;/td&gt;
&lt;td&gt;Your team designs and maintains availability&lt;/td&gt;
&lt;td&gt;Uptime commitments vary by plan; Business includes a 99.9% SLA, and Enterprise offers up to 99.99%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration control&lt;/td&gt;
&lt;td&gt;Greater control over the deployment environment&lt;/td&gt;
&lt;td&gt;Full Keycloak admin access; Skycloak manages the underlying infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational workload&lt;/td&gt;
&lt;td&gt;Higher infrastructure responsibility&lt;/td&gt;
&lt;td&gt;Reduced infrastructure maintenance for your team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost structure&lt;/td&gt;
&lt;td&gt;Infrastructure, engineering time, maintenance, and operational overhead&lt;/td&gt;
&lt;td&gt;Infrastructure-based pricing, unlimited users, and no fees tied to monthly active users&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Self-hosted Keycloak gives your team direct control over the infrastructure and responsibility for operating it. Skycloak manages the underlying infrastructure, while your team retains full Keycloak admin access and responsibility for securely integrating authentication into your application. All Skycloak plans support unlimited users, with pricing based on infrastructure rather than monthly active users.&lt;/p&gt;

&lt;p&gt;Cost also deserves a realistic comparison. A self-hosted deployment might look cheaper when you compare only server expenses with a managed service's monthly fee. Once you include engineering time, monitoring, backups, upgrades, incident response, and availability requirements, the total cost can look different.&lt;/p&gt;

&lt;p&gt;For a small team, reducing ongoing operational work may justify a managed service. For an organization with a mature platform engineering team and strict infrastructure requirements, self-hosting may be the better fit.&lt;/p&gt;


&lt;h2&gt;
  
  
  How Skycloak Makes Managed Keycloak Practical
&lt;/h2&gt;

&lt;p&gt;Self-hosting Keycloak gives your team control, but that control comes with ongoing work: maintaining the deployment, applying updates, monitoring availability, and keeping the supporting infrastructure secure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skycloak.io/" rel="noopener noreferrer"&gt;Skycloak&lt;/a&gt; provides managed hosting for upstream Keycloak. It manages the underlying infrastructure while giving your team full Keycloak admin access, so you can configure identity and authentication without operating the infrastructure yourself.&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%2Foidno87f0wta0vgw3rnn.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%2Foidno87f0wta0vgw3rnn.png" alt="Self-hosted vs managed Keycloak comparison showing password hashes stored in a database, with your team managing self-hosted infrastructure and Skycloak managing the underlying infrastructure for managed Keycloak" width="799" height="336"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Keep Keycloak's Capabilities Without Running the Infrastructure
&lt;/h3&gt;

&lt;p&gt;Skycloak runs upstream Keycloak and gives your team full Keycloak admin access. Its managed service includes the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less infrastructure maintenance:&lt;/strong&gt; Skycloak manages the underlying infrastructure, reducing the operational work your team handles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keycloak authentication features:&lt;/strong&gt; Configure SSO, MFA, SAML, and OpenID Connect (OIDC).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlimited users:&lt;/strong&gt; All plans support unlimited users, with no fees tied to monthly active users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regional deployment options:&lt;/strong&gt; Paid plans offer supported deployment regions in the US, EU, Canada, and Australia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realm export:&lt;/strong&gt; Export your realms to help plan a migration to a self-hosted Keycloak deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free trial:&lt;/strong&gt; Try Skycloak for 21 days without a credit card.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For current pricing and plan details, visit the &lt;a href="https://skycloak.io/pricing/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_passwords" rel="noopener noreferrer"&gt;Skycloak pricing page&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Does This Mean for Your Team?
&lt;/h3&gt;

&lt;p&gt;Consider a small SaaS team building its product. The developers need authentication, user management, and secure access to application resources, but they may not have a dedicated platform team to maintain an identity deployment.&lt;/p&gt;

&lt;p&gt;With self-hosted Keycloak, the team plans and maintains infrastructure provisioning, updates, backups, monitoring, and recovery alongside product development. With Skycloak, the provider manages the underlying infrastructure, while the team focuses on integrating Keycloak, configuring authentication flows, managing access, and securing application sessions.&lt;/p&gt;

&lt;p&gt;This doesn't remove the need for sound identity and application security. Your team still needs to configure roles and permissions, protect administrative access, validate redirect URIs, and make sure authenticated users can access only the resources they're authorized to use.&lt;/p&gt;

&lt;p&gt;The benefit is a clearer division of responsibilities: Skycloak operates the managed infrastructure, while your team focuses on using Keycloak securely within the application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Is Skycloak Worth Considering?
&lt;/h3&gt;

&lt;p&gt;Skycloak is worth considering if you want Keycloak's flexibility without operating the underlying infrastructure. All plans support unlimited users, and infrastructure-based pricing means your bill isn't tied to monthly active users. You can choose from supported deployment regions in the US, EU, Canada, and Australia, export realms when planning a migration, and try the service free for 21 days without a credit card.&lt;/p&gt;

&lt;p&gt;Compare the available features and prices on the &lt;a href="https://skycloak.io/pricing/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_passwords" rel="noopener noreferrer"&gt;Skycloak pricing page&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Which Keycloak Deployment Should You Choose?
&lt;/h2&gt;

&lt;p&gt;There's no universal winner. The right choice depends on your team's capabilities and the requirements of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose self-hosted Keycloak if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need extensive control over the infrastructure, network, database, or deployment architecture.&lt;/li&gt;
&lt;li&gt;Your organization already has people responsible for operating production services.&lt;/li&gt;
&lt;li&gt;You have specific requirements that a managed provider cannot meet.&lt;/li&gt;
&lt;li&gt;You're prepared to maintain upgrades, backups, monitoring, incident response, and disaster recovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose managed Keycloak with Skycloak if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want upstream Keycloak without operating the underlying identity infrastructure.&lt;/li&gt;
&lt;li&gt;You want full Keycloak admin access while reducing infrastructure maintenance.&lt;/li&gt;
&lt;li&gt;You need features such as SSO, MFA, OIDC, and SAML.&lt;/li&gt;
&lt;li&gt;You want unlimited users without fees tied to monthly active users.&lt;/li&gt;
&lt;li&gt;You need deployment options in the US, EU, Canada, or Australia.&lt;/li&gt;
&lt;li&gt;Realm export and a 21-day free trial without a credit card fit your evaluation and migration plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an early-stage SaaS product, Skycloak can provide a way to use Keycloak without building and maintaining the supporting infrastructure from scratch. Teams with established platform engineering capabilities or requirements that call for direct infrastructure control may prefer self-hosting. Evaluate both options against your security needs, engineering capacity, expected costs, and long-term plans.&lt;/p&gt;

&lt;p&gt;Before committing, ask a few concrete questions: Can you configure the authentication flows you need? Can you export or migrate your identity data? What backup and recovery guarantees exist? Who applies security updates, and how are changes communicated? What happens if the provider experiences an outage?&lt;/p&gt;

&lt;p&gt;Those answers will tell you more than the label &lt;em&gt;managed&lt;/em&gt; or &lt;em&gt;self-hosted&lt;/em&gt; alone.&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Where does Keycloak store user passwords?
&lt;/h3&gt;

&lt;p&gt;→ In a standard Keycloak deployment using its built-in user storage, password credentials are stored as password hashes in the configured database. Keycloak does not need to store the original passwords in readable plaintext. If the deployment uses an external user store, credential storage may be handled by that system.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Skycloak, and how does it differ from self-hosted Keycloak?
&lt;/h3&gt;

&lt;p&gt;→ Skycloak is a managed Keycloak service that runs the upstream Keycloak platform and manages the underlying infrastructure. With self-hosted Keycloak, your team operates the deployment and supporting services. With Skycloak, infrastructure responsibilities covered by the service move to the provider, while your team continues to manage application integration and identity configuration.&lt;/p&gt;
&lt;h3&gt;
  
  
  Can I use passkeys with self-hosted and managed Keycloak?
&lt;/h3&gt;

&lt;p&gt;→ Yes. Keycloak supports WebAuthn-based authentication, including passwordless passkey flows, when configured appropriately. The exact setup depends on your Keycloak version, authentication flow, and environment. With a managed service, confirm that the provider supports the configuration and administrative access your application needs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Who manages security when using Skycloak?
&lt;/h3&gt;

&lt;p&gt;→ Security responsibilities are shared. Skycloak manages the underlying infrastructure, while your team uses its full Keycloak admin access to configure authentication, protect administrative accounts, assign appropriate permissions, and integrate Keycloak securely into the application. Your team should still verify any specific uptime, backup, and recovery commitments it requires.&lt;/p&gt;
&lt;h3&gt;
  
  
  Is self-hosted Keycloak cheaper than managed Keycloak?
&lt;/h3&gt;

&lt;p&gt;→ It can be, but server costs alone don't show the full picture. Self-hosting also requires engineering time for updates, monitoring, backups, troubleshooting, and incident response. Managed Keycloak introduces service fees but may reduce those operational costs. Compare the total cost of ownership for your expected workload and team capacity.&lt;/p&gt;


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

&lt;p&gt;Self-hosting gives you direct responsibility for the deployment, database, updates, and availability. Skycloak lets you keep using upstream Keycloak with full Keycloak admin access while the provider manages the underlying infrastructure. &lt;/p&gt;

&lt;p&gt;All plans support unlimited users, and the service offers deployment regions in the US, EU, Canada, and Australia. You can try Skycloak for free for 21 days without a credit card.&lt;/p&gt;

&lt;p&gt;Choose the setup that protects your users' identities and gives your team a clear, sustainable way to manage authentication as your product grows.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>programming</category>
      <category>development</category>
      <category>authentication</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Stop Shipping Marketing Pages Like Product Features</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:02:59 +0000</pubDate>
      <link>https://dev.to/yassersoliman/stop-shipping-marketing-pages-like-product-features-374d</link>
      <guid>https://dev.to/yassersoliman/stop-shipping-marketing-pages-like-product-features-374d</guid>
      <description>&lt;p&gt;A marketing page workflow should help your team launch campaigns, update messaging, and improve conversions without turning every small website change into a development project.&lt;/p&gt;

&lt;p&gt;Yet, in many B2B SaaS companies, updating a headline, adding a customer story, or launching a new landing page can require the same process as shipping a product feature. Marketing submits a request, engineering reviews it, priorities compete for attention, and a simple update waits in the backlog.&lt;/p&gt;

&lt;p&gt;This usually happens because teams use one process for two different kinds of work. Product developers have roadmaps, technical tasks, and deadlines of their own. They need time to build and maintain the product, while marketing needs to keep the website and campaigns up to date.&lt;/p&gt;

&lt;p&gt;Over time, this setup can slow down campaigns, delay conversion improvements, and leave marketing teams waiting for developers to make routine changes. It can also push teams toward quick fixes that lead to inconsistent designs, tracking issues, and extra technical work later.&lt;/p&gt;

&lt;p&gt;A better marketing page workflow gives marketing more freedom while keeping engineering involved where technical skills matter. The goal is to make website updates easier to publish, safer to maintain, and easier to measure.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Stop shipping marketing pages like product features by creating a dedicated marketing page workflow with clear ownership, reusable components, the right publishing permissions, and simple quality checks.&lt;/p&gt;

&lt;p&gt;Marketing should handle routine content and campaign updates through an approved process. Engineering should set the technical standards, maintain shared components, and review changes that affect security, architecture, integrations, or complex features.&lt;/p&gt;

&lt;p&gt;Before a page goes live, the team should check its mobile layout, links, forms, analytics, SEO basics, and performance. This approach helps B2B SaaS teams launch campaigns faster without sacrificing website quality or reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Marketing Page Updates Get Stuck in the Product Backlog
&lt;/h2&gt;

&lt;p&gt;When marketing page updates follow the same process as product features, they compete for time with work that may have a higher priority on the engineering roadmap.&lt;/p&gt;

&lt;p&gt;A marketing team might need to change a headline before a campaign launches, add a new customer story, or test a landing page. However, the request may wait days or weeks while developers work on product releases, bug fixes, and technical projects.&lt;/p&gt;

&lt;p&gt;These delays affect more than publishing dates. A campaign may launch with outdated messaging, a useful conversion improvement may sit on hold, or a small change may miss its window entirely.&lt;/p&gt;

&lt;p&gt;The issue often comes from the workflow, not the people involved. &lt;a href="https://yassersoliman.com/blog/why-marketing-teams-cant-get-dev-to-prioritize-website-requests/" rel="noopener noreferrer"&gt;Marketing requests often compete with product work&lt;/a&gt; because engineering backlogs are built around product priorities. Developers need to protect their time for complex technical work, while marketers need a reliable way to make approved website changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A dedicated marketing page workflow helps separate routine website updates from product development.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It gives each type of work a clear path, with the right people involved at the right time.&lt;/p&gt;

&lt;p&gt;For example, changing a headline should usually be a simple content update. Adding a new feature that connects to an application API may need engineering input. Treating both requests the same way creates extra work for everyone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Marketing Pages Have Different Requirements From Product Features
&lt;/h2&gt;

&lt;p&gt;Product features and marketing pages support different goals. Product teams focus on functionality, reliability, and user needs. Marketing teams focus on messaging, campaigns, lead generation, and conversion rates.&lt;/p&gt;

&lt;p&gt;Those goals affect how each type of work should move through a team.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Product features&lt;/th&gt;
&lt;th&gt;Marketing pages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main goal&lt;/td&gt;
&lt;td&gt;Improve the product experience&lt;/td&gt;
&lt;td&gt;Attract, inform, and convert visitors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common changes&lt;/td&gt;
&lt;td&gt;Application logic, APIs, and user features&lt;/td&gt;
&lt;td&gt;Headlines, landing pages, testimonials, and campaign content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Priorities&lt;/td&gt;
&lt;td&gt;Product roadmap, customer needs, and reliability&lt;/td&gt;
&lt;td&gt;Campaign dates, messaging, and conversion opportunities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Publishing process&lt;/td&gt;
&lt;td&gt;Development, testing, and release&lt;/td&gt;
&lt;td&gt;Content review, quality checks, and publishing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success measures&lt;/td&gt;
&lt;td&gt;Product usage, reliability, and retention&lt;/td&gt;
&lt;td&gt;Leads, conversions, engagement, and campaign results&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are common patterns, not fixed rules. A complex landing page with custom integrations may need substantial engineering work, while a small product copy change may be easy to publish.&lt;/p&gt;

&lt;p&gt;The important thing is to match the process to the work. A marketing page workflow should let teams handle routine updates quickly while keeping the right technical checks in place for more complex changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Build a Marketing Page Workflow That Fits the Work
&lt;/h2&gt;

&lt;p&gt;A useful workflow gives every website request a clear path from the first idea to the final results. It should also make ownership, review needs, and expected turnaround times easy to understand.&lt;/p&gt;

&lt;p&gt;A simple process can include five stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Request:&lt;/strong&gt; Marketing explains the goal, audience, content, and deadline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create:&lt;/strong&gt; The team builds the page using approved templates and components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review:&lt;/strong&gt; The right people check the content, design, functionality, and tracking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publish:&lt;/strong&gt; An authorized team member launches the page and checks the live version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure:&lt;/strong&gt; The team reviews performance and uses the results to guide future changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Not every request needs the same level of review. A headline change may only need a quick content check, while a new lead form could require testing, analytics checks, and an engineering review.&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%2F8wexa9lpc5zcd7z8oain.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%2F8wexa9lpc5zcd7z8oain.png" alt="Marketing page workflow showing request, creation, review, publishing, and performance measurement stages" width="799" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clear ownership also prevents requests from getting lost. Marketing should know who prepares the page, who approves the content, and who can publish it. Engineering should know when a request needs technical review.&lt;/p&gt;

&lt;p&gt;With these steps in place, a marketing page workflow becomes easier to follow and less dependent on ad hoc requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Give Marketing Reusable Components, Not Unlimited Freedom
&lt;/h2&gt;

&lt;p&gt;Marketing teams need room to create pages that fit different campaigns. However, building every page from scratch can lead to inconsistent layouts, repeated work, and more maintenance for developers.&lt;/p&gt;

&lt;p&gt;Reusable components offer a practical way to balance speed and consistency. These can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testimonials and customer story blocks&lt;/li&gt;
&lt;li&gt;Product comparison tables&lt;/li&gt;
&lt;li&gt;Customer logo sections&lt;/li&gt;
&lt;li&gt;FAQs and call-to-action blocks&lt;/li&gt;
&lt;li&gt;Lead forms and contact sections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the team uses approved components, marketers can assemble pages without rebuilding common elements each time. Developers can maintain those components in one place, making it easier to fix issues and improve the overall design.&lt;/p&gt;

&lt;p&gt;Still, reusable components need clear rules. Teams should document which parts marketers can edit, what they can customize, and when a new component requires engineering support.&lt;/p&gt;

&lt;p&gt;The right setup depends on the website platform and the team's needs. A content management system (CMS) with flexible page templates may offer enough control for routine updates. More complex pages may still need custom development.&lt;/p&gt;

&lt;p&gt;The goal is to give marketing useful tools and clear boundaries, so the team can work independently without creating avoidable technical problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Set Clear Publishing Permissions and Quality Checks
&lt;/h2&gt;

&lt;p&gt;A good marketing page workflow should explain who can edit, review, and publish each type of change. These permissions help teams move quickly while protecting the website from mistakes.&lt;/p&gt;

&lt;p&gt;For example, marketers may be able to edit page copy and use approved components. Engineering may handle shared templates, JavaScript, complex integrations, and changes that affect security or site-wide behavior.&lt;/p&gt;

&lt;p&gt;This setup keeps routine work moving while giving technical changes the attention they need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a Simple Pre-Publish Checklist
&lt;/h3&gt;

&lt;p&gt;Before publishing a landing page, check the areas that can affect visitors, conversions, and search visibility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Content:&lt;/strong&gt; Is the copy accurate, clear, and free of errors?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile layout:&lt;/strong&gt; Does the page work well on different screen sizes?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Links and forms:&lt;/strong&gt; Do links, form submissions, and confirmation messages work?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics:&lt;/strong&gt; Do conversion events and tracking tools record the right data?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO:&lt;/strong&gt; Are the page title, metadata, canonical URL, and indexing settings correct?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance and accessibility:&lt;/strong&gt; Does the page load well, and can people use it easily?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publishing safety:&lt;/strong&gt; Can the team restore the previous version if something goes wrong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Google's guidance on making pages eligible to appear in search results, review the &lt;a href="https://developers.google.cn/search/docs/essentials?hl=en" rel="noopener noreferrer"&gt;Google Search Essentials guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not every update needs a full technical review. A small text change may need only a quick check, while a new form or custom integration deserves more testing.&lt;/p&gt;

&lt;p&gt;After publishing, someone should check the live page to confirm that it looks right and works as expected. This final step can catch problems that were missed during review.&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%2Fa6tof6lgkwlw6ayad2ts.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%2Fa6tof6lgkwlw6ayad2ts.png" alt="Marketing landing page quality checks for mobile layout, forms, analytics, SEO, performance, and accessibility" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Measure Whether Your Marketing Page Workflow Is Working
&lt;/h2&gt;

&lt;p&gt;A marketing page workflow should make publishing easier, but teams need a way to tell whether it is helping. A few useful measures can show where delays remain and whether the process is improving.&lt;/p&gt;

&lt;p&gt;Start with the time it takes to move from a request to a live page. If routine updates still wait in the backlog, the team may need clearer ownership or a simpler approval process.&lt;/p&gt;

&lt;p&gt;It also helps to track how often campaign deadlines are missed, how many issues appear after publishing, and whether forms and conversion events work as expected.&lt;/p&gt;

&lt;p&gt;Conversion rates matter, too, but they need context. A page may attract more visitors while generating fewer qualified leads. Teams should look at campaign goals, lead quality, and tracking reliability alongside conversion numbers.&lt;/p&gt;

&lt;p&gt;Use these results to improve the workflow over time. If content reviews cause delays, clarify who approves copy. If pages often break on mobile, improve the shared templates or pre-publish checks.&lt;/p&gt;

&lt;p&gt;The aim is not to add more reporting. It is to understand where the process slows down and make the next update easier to ship.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a marketing page workflow?
&lt;/h3&gt;

&lt;p&gt;→ marketing page workflow is the process a team follows to plan, create, review, publish, and measure website updates. It defines who handles each step, which changes need approval, and what checks must happen before a page goes live. A clear workflow helps marketing teams publish updates with fewer delays and fewer avoidable errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why shouldn't marketing pages follow the same process as product features?
&lt;/h3&gt;

&lt;p&gt;→ Marketing pages and product features have different goals, deadlines, and technical needs. Routine page updates often need a quick review, while product features may require development, testing, and release planning. A dedicated marketing page workflow helps teams publish campaign updates faster while keeping engineering involved in changes that need technical expertise.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can marketing teams update website pages without depending on developers?
&lt;/h3&gt;

&lt;p&gt;→ Teams can use a CMS, approved page templates, and reusable components to handle routine website changes. Clear publishing permissions and simple guidelines also help marketers understand what they can update on their own. Developers can then focus on shared components, complex features, integrations, and technical issues that need their attention.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should teams check before publishing a landing page?
&lt;/h3&gt;

&lt;p&gt;→ Teams should review the content, mobile layout, links, forms, analytics, SEO settings, performance, and accessibility. They should also confirm that the correct page version is live and that a rollback is possible if an issue appears. The depth of the checks should match the type and risk of the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who should own a B2B SaaS marketing website?
&lt;/h3&gt;

&lt;p&gt;→ A B2B SaaS company should assign clear responsibility for its marketing website. Marketing usually owns messaging, campaign priorities, and conversion goals, while engineering maintains technical standards and handles complex changes. A WebOps lead can connect these responsibilities, improve the publishing process, and help the website support the company's growth goals.&lt;/p&gt;




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

&lt;p&gt;Marketing teams should not have to choose between publishing quickly and keeping their website reliable. A clear marketing page workflow helps them handle routine updates, launch campaigns on time, and test new ideas without sending every small request to engineering.&lt;/p&gt;

&lt;p&gt;The key is to give each team clear responsibilities, provide reusable components, set sensible publishing permissions, and apply quality checks that match the work. Engineering can protect the technical foundations while marketing gets more control over everyday website updates.&lt;/p&gt;

&lt;p&gt;For B2B SaaS companies, this is an important part of WebOps: keeping the marketing website useful, reliable, and ready to support business goals.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What website change is your team waiting too long to ship, and what would make that process easier?&lt;/em&gt;&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>marketing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Heard AI Could Build Its Own UI, So I Tried Open Intelligent UI</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Fri, 16 Oct 2026 09:03:58 +0000</pubDate>
      <link>https://dev.to/hadil/i-heard-ai-could-build-its-own-ui-so-i-tried-open-intelligent-ui-24dh</link>
      <guid>https://dev.to/hadil/i-heard-ai-could-build-its-own-ui-so-i-tried-open-intelligent-ui-24dh</guid>
      <description>&lt;p&gt;Artificial intelligence has changed the way by which developers are making applications, which range from code generation and debugging tasks to assisting clients in searching for information and automating various tasks.&lt;/p&gt;

&lt;p&gt;However, AI applications can provide more than just answers. The applications can also give information through interfaces which contain elements needed to realize the tasks of users.&lt;/p&gt;

&lt;p&gt;This is where generative UI comes in. It allows AI-powered applications to generate or assemble user interfaces, making it possible to turn a natural-language request into something users can explore, customize, and interact with.&lt;/p&gt;

&lt;p&gt;For developers, this opens up new possibilities for building AI assistants, interactive dashboards, planning tools, and applications that adapt their interfaces to different requests.&lt;/p&gt;

&lt;p&gt;I wanted to see how Open Intelligent UI handled different requests, what the generated interfaces looked like, and whether the results were genuinely interactive. After testing three prompts, I decided to share my experience alongside a practical guide to running the demo locally.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain the basics of generative UI, introduce OpenUI, and walk you through setting up and exploring the Open Intelligent UI demo.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Generative UI lets AI-powered applications create interfaces that help users do more with an answer. Instead of receiving only text, users can interact with structured content, forms, tables, maps, and other UI components.&lt;/p&gt;

&lt;p&gt;Here's what you can explore with Open Intelligent UI and the tools behind it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open-source demo:&lt;/strong&gt; Run the &lt;a href="https://github.com/thesysdev/open-intelligent-ui" rel="noopener noreferrer"&gt;Open Intelligent UI repository&lt;/a&gt; locally and experiment with AI-generated interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive experiences:&lt;/strong&gt; Build AI-powered interfaces with components suited to different tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple model options:&lt;/strong&gt; Use supported models through OpenUI Cloud, including eligible free models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A free starting point:&lt;/strong&gt; The published OpenUI Cloud plan offers 3,000 OpenUI Cloud API calls per month, subject to its current terms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can run the demo locally with Node.js, an OpenUI Cloud API Key, and a few terminal commands. I'll also share my hands-on results, so you can see what the experience looks like.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Generative UI, and Why Does It Matter?
&lt;/h2&gt;

&lt;p&gt;Most AI chat interfaces follow a familiar pattern: you ask a question, and the model replies with text. That works well for explanations, brainstorming, and quick answers, but some tasks are easier to handle through an interface.&lt;/p&gt;

&lt;p&gt;Imagine asking an AI to compare React, Vue, and Svelte. A written explanation can cover their differences, but an interactive table could let you scan strengths and weaknesses more easily.&lt;/p&gt;

&lt;p&gt;Generative UI is an approach where AI generates or assembles a user interface in response to a request. The interface can include structured content and interactive components that make the answer easier to explore and use.&lt;/p&gt;

&lt;p&gt;The exact result depends on the system, its available components, and the model powering it. Some implementations generate interface descriptions that a renderer turns into UI components; others rely on predefined tools and component libraries. &lt;/p&gt;

&lt;p&gt;The goal is to make the response fit the task.&lt;/p&gt;

&lt;p&gt;This approach can be useful in several daily scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Travel planning:&lt;/strong&gt; Display destinations, maps, photos, and an itinerary that users can edit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data comparison:&lt;/strong&gt; Present products, frameworks, or services in a structured table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forms and planning tools:&lt;/strong&gt; Let users choose options, adjust settings, and build a result around their preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI assistants for business applications:&lt;/strong&gt; Give users controls and structured information that help them complete a task within an existing workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generative UI doesn't automatically make every AI answer better. A simple factual question may need only a sentence or two. The value becomes clearer when the user needs to compare options, adjust inputs, explore information, or take the next step.&lt;/p&gt;

&lt;p&gt;That's what I wanted to explore with Open Intelligent UI: how generative UI works when you can interact with the results yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is OpenUI?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.openui.com/" rel="noopener noreferrer"&gt;OpenUI&lt;/a&gt; is an open standard for generative UI that helps developers build AI-powered applications with rich, structured, and interactive interfaces.&lt;/p&gt;

&lt;p&gt;OpenUI provides tooling for turning AI-generated responses into UI components that users can explore and interact with. &lt;a href="https://www.openui.com/docs/gateway/models" rel="noopener noreferrer"&gt;OpenUI Gateway&lt;/a&gt; provides access to supported AI models through a common API.&lt;/p&gt;

&lt;p&gt;To see how this works in practice, you can explore the &lt;a href="https://github.com/thesysdev/open-intelligent-ui" rel="noopener noreferrer"&gt;Open Intelligent UI repository&lt;/a&gt;. It contains an open-source demo application that you can run locally, experiment with using your own prompts, and adapt to explore generative UI in practice.&lt;/p&gt;

&lt;p&gt;It's worth distinguishing the two names: OpenUI refers to the broader tooling and platform, while Open Intelligent UI is a demo application.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Can You Explore With Open Intelligent UI?
&lt;/h2&gt;

&lt;p&gt;Open Intelligent UI gives developers a hands-on way to explore how AI can turn natural-language prompts into interactive user interfaces. You can experiment with different requests and see how the demo presents information based on the task.&lt;/p&gt;

&lt;p&gt;Here are a few examples of what you can explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interactive travel planners:&lt;/strong&gt; Generate an itinerary with destinations, photos, and a map that users can explore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology comparisons:&lt;/strong&gt; Present information about frameworks, tools, or products in a structured table with strengths, weaknesses, and recommendations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forms and planning tools:&lt;/strong&gt; Create interfaces with input fields, dropdowns, checkboxes, and buttons that let users customize their choices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured AI responses:&lt;/strong&gt; Organize information into layouts that are easier to scan and interact with than a long text response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different interface patterns:&lt;/strong&gt; Experiment with prompts to see how the generated interface changes depending on the information users need and the actions they want to take.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The results depend on the prompt, the model, and the tools and components supported by the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing a Model for Open Intelligent UI
&lt;/h2&gt;

&lt;p&gt;The model you choose affects how well Open Intelligent UI follows your prompt and generates a useful interface. Model capabilities, response speed, and cost can all influence the results, so it's worth checking compatibility before settling on one.&lt;/p&gt;

&lt;p&gt;OpenUI Gateway gives developers access to different models through a common API. You can choose a model that fits your budget and experiment with different options as your application evolves. Check the &lt;a href="https://www.openui.com/cloud/gateway/models" rel="noopener noreferrer"&gt;OpenUI Gateway models list&lt;/a&gt; for available models and their capabilities.&lt;/p&gt;

&lt;p&gt;You can also connect a locally running LLM through Ollama. The Open Intelligent UI demo supports Ollama through its OpenAI-compatible Chat Completions endpoint, allowing you to experiment with local models instead of relying on OpenUI Gateway for model inference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Free Models Worth Exploring
&lt;/h3&gt;

&lt;p&gt;At the time of my test, the free-model options I identified included:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;google/gemini-3.6-flash-free&lt;/code&gt;&lt;br&gt;
&lt;code&gt;google/gemini-3.5-flash-free&lt;/code&gt;&lt;br&gt;
&lt;code&gt;google/gemini-3.1-pro-free&lt;/code&gt;&lt;br&gt;
&lt;code&gt;google/gemini-3.1-flash-lite-free&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy note:&lt;/strong&gt; OpenUI Gateway's documentation states that requests sent to free models may be used for model training. Avoid submitting sensitive or confidential information when experimenting with these models, and review the current data-handling terms before using them. &lt;/p&gt;

&lt;p&gt;I chose &lt;code&gt;google/gemini-3.6-flash-free&lt;/code&gt; for my experiment because I wanted to try OpenUI without adding a separate paid model API key.&lt;/p&gt;

&lt;p&gt;However, there's an important detail worth knowing before you choose a model. &lt;/p&gt;

&lt;p&gt;A model being available through the gateway doesn't guarantee that it supports every feature used by a particular application. The Open Intelligent UI demo uses the Responses API and gateway-hosted tools, including image search, so compatibility needs to be checked with the actual application.&lt;/p&gt;

&lt;p&gt;For my experiment, the free model was a practical starting point. If you encounter errors or some features don't work as expected, check the model's supported capabilities and the application's logs before assuming the whole project is broken.&lt;/p&gt;


&lt;h2&gt;
  
  
  How to Run Open Intelligent UI Locally: My Hands-On Test
&lt;/h2&gt;

&lt;p&gt;Let's get the demo running.&lt;/p&gt;

&lt;p&gt;I chose the existing Open Intelligent UI project so I could explore its generated interfaces without building a separate application from scratch.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Create a Thesys Account and Get Your API Key
&lt;/h3&gt;

&lt;p&gt;First, visit the &lt;a href="https://console.thesys.dev" rel="noopener noreferrer"&gt;Thesys Console&lt;/a&gt; and create an account or sign in.&lt;/p&gt;

&lt;p&gt;From the console, open the AI Gateway setup and generate an API key. This key allows your local application to make requests through OpenUI Cloud.&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%2Fm7bpay2nfa190gfywmf4.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%2Fm7bpay2nfa190gfywmf4.png" alt="Create a Thesys Account and Get Your API Key" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;
Generating an API key in the Thesys Console before configuring the local application.
&amp;nbsp;

&lt;p&gt;The OpenUI Gateway Free plan includes &lt;strong&gt;3,000 API calls per month&lt;/strong&gt;. Each generated response uses an API call, while model-token charges depend on the model you choose. Some eligible models have no token charges, although usage limits may apply. Check the &lt;a href="https://www.openui.com/docs/gateway/pricing-credits" rel="noopener noreferrer"&gt;current pricing and credits documentation&lt;/a&gt; before getting started.&lt;/p&gt;

&lt;p&gt;Keep your API key private. You'll add it to a local environment file, so there's no reason to put it in your source code or publish it in a repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Clone the Open Intelligent UI Repository
&lt;/h3&gt;

&lt;p&gt;You'll need Git and Node.js installed on your machine. The repository's README specifies &lt;strong&gt;Node.js 24&lt;/strong&gt;, so check your version before proceeding.&lt;/p&gt;

&lt;p&gt;Open a terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/thesysdev/open-intelligent-ui.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Move into the project directory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;open-intelligent-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Install the dependencies:&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;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This installs the packages the application needs to run. Depending on your internet connection and package cache, the installation may take a little time.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Configure Your API Key and Model
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file in the project's root directory. The repository includes a &lt;code&gt;.env.example&lt;/code&gt; file you can use as a reference, but the local configuration should be saved in &lt;code&gt;.env.local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following lines:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;THESYS_API_KEY=YOUR_THESYS_API_KEY
THESYS_MODEL=YOUR_MODEL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replace &lt;code&gt;YOUR_THESYS_API_KEY&lt;/code&gt; with the key you generated in the Thesys Console and &lt;code&gt;YOUR_MODEL&lt;/code&gt; with the model you chose.&lt;/p&gt;

&lt;p&gt;The two variables have different jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;THESYS_API_KEY&lt;/code&gt; authenticates your requests to the gateway.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;THESYS_MODEL&lt;/code&gt; tells the application which model to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second variable is optional in the project configuration, but setting it explicitly makes your chosen model clear. If you want to try another model later, you can change its ID here, provided that the model is available and compatible with the application's API and tools.&lt;/p&gt;
&lt;h4&gt;
  
  
  Optional: Connect a Local Model With Ollama
&lt;/h4&gt;

&lt;p&gt;If you prefer to run a model locally, you can configure the demo to use Ollama instead of OpenUI Gateway.&lt;/p&gt;

&lt;p&gt;First, install Ollama, download a model supported by your setup, and make sure the Ollama service is running. For example, you can download a model using:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull qwen3.8:27b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then update your &lt;code&gt;.env.local&lt;/code&gt; file with the Ollama configuration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MODEL_PROVIDER=ollama
OLLAMA_MODEL=qwen3.8:27b
OLLAMA_BASE_URL=http://localhost:11434/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These settings select Ollama as the model provider, specify the local model, and configure the OpenAI-compatible API base URL.&lt;/p&gt;

&lt;p&gt;Restart the development server after changing your environment variables. Check Ollama's &lt;a href="https://docs.ollama.com/api/openai-compatibility" rel="noopener noreferrer"&gt;OpenAI compatibility documentation&lt;/a&gt; for the latest configuration details.&lt;/p&gt;

&lt;p&gt;Local inference means the model runs on your machine, so the available performance depends on your hardware and the model you select.&lt;/p&gt;

&lt;p&gt;Make sure &lt;code&gt;.env.local&lt;/code&gt; stays out of Git commits and public repositories.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4: Start the Application
&lt;/h3&gt;

&lt;p&gt;With your environment file saved, run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once the development server starts, open &lt;code&gt;http://localhost:3000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;p&gt;You should see the demo's chat-style interface, ready for you to enter a prompt.&lt;/p&gt;

&lt;p&gt;If you've changed the environment variables while the server is running, stop it with &lt;code&gt;Ctrl+C&lt;/code&gt; and start it again. &lt;/p&gt;

&lt;p&gt;If the interface loads but sending a prompt fails, check the terminal output and browser developer console for errors. An API key issue, model compatibility problem, or failed tool call may prevent a response from being generated.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5: Try Some Prompts
&lt;/h3&gt;

&lt;p&gt;I tested three prompts covering different use cases: visual trip planning, technology comparisons, and an interactive form.&lt;/p&gt;

&lt;p&gt;Here's what I asked the demo to generate in each case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 1: Plan a trip&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan a one-day trip in San Francisco. Show the stops in order, include photos and an interactive map, and make the itinerary editable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I wanted to see whether the demo could combine a useful itinerary with visual context and an interactive map. The editable itinerary was also important because travel plans are much more useful when you can adjust them to suit your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 2: Compare frontend frameworks&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compare React, Vue, and Svelte for a beginner building a small web application. Show the comparison in an interactive table with strengths, weaknesses, and a recommendation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This prompt explored a different kind of task: presenting information in a structured format. I wanted to see how the generated UI would organize the comparison and whether the result would be easier to explore than a conventional text response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt 3: Build a weekend-trip planner&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create an interactive weekend-trip planner with a destination field, a budget selector, a trip-duration selector, and a button to generate a suggested itinerary.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These prompts cover three different needs: displaying visual information, comparing technologies, and generating an interface with form controls. Your results may vary depending on the model and the features supported by the application.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/qDtYXmKsgV4" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The screenshots below will give you a closer look at each result.&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%2F9p69evrlevagbd3thg2t.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%2F9p69evrlevagbd3thg2t.png" alt="Open Intelligent UI generating a San Francisco itinerary with photos, ordered stops, and an interactive map." width="800" height="2010"&gt;&lt;/a&gt;&lt;/p&gt;
A San Francisco sightseeing itinerary combining photos, ordered stops, and an interactive map.
&amp;nbsp;

&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%2Fxa814v78ef0f6ul7me9i.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%2Fxa814v78ef0f6ul7me9i.png" alt="Expanded interactive map in the Open Intelligent UI travel-planning demo." width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;
Expanded view of the map.
&amp;nbsp;

&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%2F4ta3vw2gckyud0sbluid.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%2F4ta3vw2gckyud0sbluid.png" alt="Open Intelligent UI displaying a comparison of React, Vue, and Svelte with strengths, weaknesses, and a recommendation." width="800" height="1011"&gt;&lt;/a&gt;&lt;/p&gt;
Comparing three frontend frameworks in a structured table generated from a single prompt.
&amp;nbsp;

&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%2Fk24zjo24e1gukrswnxki.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%2Fk24zjo24e1gukrswnxki.png" alt="Open Intelligent UI weekend-trip planner with a destination input, budget selector, trip-duration selector, and itinerary generation button." width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;
Form-driven interface with controls for customizing a weekend trip.



&lt;h2&gt;
  
  
  What I Loved About Open Intelligent UI
&lt;/h2&gt;

&lt;p&gt;My experience with Open Intelligent UI was genuinely positive. The generated interfaces looked clean and polished, and the response time was pretty quick. I was impressed by the quality of the results, especially considering that I was using a free model for my test.&lt;/p&gt;

&lt;p&gt;The interaction itself was another big plus. I could click buttons, check boxes, change dropdown selections, and explore the map in the travel-planning interface. Being able to try the generated components directly made the experience feel much more engaging.&lt;/p&gt;

&lt;p&gt;I also appreciated how the interface could take different forms depending on the request. A trip itinerary benefits from photos and a map, a framework comparison works well as a table, and a weekend planner needs fields and selectors. The demo gave me a chance to see those different layouts without having to design each one manually.&lt;/p&gt;

&lt;p&gt;For a demo that you can run locally and experiment with yourself, it was a genuinely rewarding introduction to generative UI.&lt;/p&gt;


&lt;h2&gt;
  
  
  Who Is Open Intelligent UI For?
&lt;/h2&gt;

&lt;p&gt;Open Intelligent UI is worth exploring if you want to see how generative UI works in a real application and experiment with AI-generated interfaces without building everything from scratch.&lt;/p&gt;

&lt;p&gt;It may be useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend developers&lt;/strong&gt; who want to explore how AI-generated responses can become interactive tables, forms, maps, and other UI components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-stack developers&lt;/strong&gt; looking for a starting point to experiment with generative UI in a web application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI application builders&lt;/strong&gt; exploring ways to make conversational experiences more interactive and task-oriented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product teams and technical founders&lt;/strong&gt; who want to prototype AI-powered planning tools, comparison interfaces, or interactive assistants.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers learning generative UI&lt;/strong&gt; who want to study an existing implementation and experiment with their own prompts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository gives you a working starting point, but adapting it to your own application will depend on your requirements, the model you choose, and the components and tools your experience needs.&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;If you find this useful, consider starring the GitHub repo&lt;/strong&gt;; it helps the project grow and signals support for open‑source infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/thesysdev/open-intelligent-ui" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;⭐ Star Open Intelligent UI on GitHub&lt;/a&gt;
&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. What is Open Intelligent UI?
&lt;/h3&gt;

&lt;p&gt;→ Open Intelligent UI is an open-source demo application from Thesys that lets developers explore generative UI in practice. You can run it locally, send prompts, and see how an AI-powered application can present responses through interactive interfaces.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. What can you do with Open Intelligent UI?
&lt;/h3&gt;

&lt;p&gt;→ You can experiment with prompts that generate different interface experiences, such as travel itineraries with maps, framework comparisons, and forms with interactive controls. It's a useful starting point for understanding how generative UI works and exploring ideas for your own AI-powered applications.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Can I run Open Intelligent UI locally?
&lt;/h3&gt;

&lt;p&gt;→ Yes. You can clone the Open Intelligent UI repository, install its dependencies with &lt;code&gt;npm install&lt;/code&gt;, configure your &lt;code&gt;.env.local&lt;/code&gt; file with your OpenUI Cloud API Key and preferred model, and start the development server with &lt;code&gt;npm run dev&lt;/code&gt;. Follow the repository's README for the latest prerequisites and setup instructions.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. How is generative UI different from a regular AI chatbot?
&lt;/h3&gt;

&lt;p&gt;→ A conventional AI chatbot generally presents its answers as text, sometimes with links or basic formatting. Generative UI can also produce or assemble interfaces such as interactive tables, forms, maps, and controls, allowing users to explore information and adjust options directly.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Is generative UI suitable for production applications?
&lt;/h3&gt;

&lt;p&gt;→ It can be, depending on the use case and implementation. Before deploying a generative UI experience, test the generated components, validate important information, handle failed requests, and consider accessibility, security, privacy, performance, and API costs.&lt;/p&gt;


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

&lt;p&gt;Open Intelligent UI offers developers a practical way to explore generative UI through an existing, open-source application. You can run it locally, experiment with prompts, and see how AI-generated interfaces respond to different tasks.&lt;/p&gt;

&lt;p&gt;If you're interested in building more interactive AI-powered experiences, take a look at the Open Intelligent UI repository on GitHub, run it locally, and experiment with prompts related to your own projects.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What would you build with Open Intelligent UI?&lt;/em&gt;&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>ai</category>
      <category>uidesign</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Removed Passwords From My App. Here’s What the Login Flow Looks Like Now</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Wed, 14 Oct 2026 13:13:55 +0000</pubDate>
      <link>https://dev.to/hadil/i-removed-passwords-from-my-app-heres-what-the-login-flow-looks-like-now-51k9</link>
      <guid>https://dev.to/hadil/i-removed-passwords-from-my-app-heres-what-the-login-flow-looks-like-now-51k9</guid>
      <description>&lt;p&gt;Most applications eventually face login problems that have little to do with their core purpose.&lt;/p&gt;

&lt;p&gt;Users forget passwords, reuse credentials, and struggle with account recovery. Meanwhile, developers must consider credential security, brute-force protection, and session management.&lt;/p&gt;

&lt;p&gt;This is the reason why I started looking into &lt;strong&gt;passwordless authentication&lt;/strong&gt; and how passkeys can potentially alter the login experience.&lt;/p&gt;

&lt;p&gt;The idea is simple: users should be able to prove their identity without typing a conventional password every time they sign in.&lt;/p&gt;

&lt;p&gt;Passkeys use public-key cryptography through standards such as WebAuthn. Users authenticate with a compatible device or security key, while the identity provider verifies the authentication and completes the login flow.&lt;/p&gt;

&lt;p&gt;I was curious to find out what implications it has for developers: how the login procedure would change, what configuration the developers have to do, and which responsibilities remain with the app.&lt;/p&gt;

&lt;p&gt;To answer these questions, I will explore the technology of passkey authentication and review Skycloak's managed Keycloak solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Passwordless authentication enables users to log in to their accounts without typing in a traditional password. With passkeys, the browser and the user's authenticator handle a cryptographic challenge, and the identity provider verifies the result.&lt;/p&gt;

&lt;p&gt;Here are the important points for developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The traditional password step is replaced with passkeys.&lt;/strong&gt; When users authenticate using the passkey, they must use a suitable device or security key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebAuthn enables public-key authentication.&lt;/strong&gt; The authenticator uses a private key to respond to a challenge, and the identity provider verifies the response using the registered public key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity providers manage authentication.&lt;/strong&gt; Keycloak supports passkeys, while &lt;a href="https://skycloak.io/" rel="noopener noreferrer"&gt;Skycloak&lt;/a&gt; offers a managed Keycloak solution with a passkey setup provided.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As usual, recovery must be taken care of.&lt;/strong&gt; One must not forget that the users could end up losing their devices or switching browsers and want to register a passkey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passwordless doesn't automatically mean MFA.&lt;/strong&gt; Whether additional authentication factors are required depends on the configured authentication policy. A passkey can also satisfy multiple authentication-factor requirements in supported flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main benefit is a simpler sign-in experience with strong phishing resistance when passkeys are correctly implemented. The trade-off is that developers still need to manage registration, recovery, device compatibility, and session security carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  Passwords Were Only the Beginning of the Problem
&lt;/h2&gt;

&lt;p&gt;A login form looks simple from the outside. A user enters their credentials, the server verifies them, and the application starts a session. The complexity appears when something goes wrong.&lt;/p&gt;

&lt;p&gt;Users forget passwords, attackers try leaked credentials, and account recovery can become a security weakness if it's poorly designed.&lt;/p&gt;

&lt;p&gt;Developers must also protect stored passwords, limit repeated login attempts, and make sure reset links can't be abused.&lt;/p&gt;

&lt;p&gt;For a growing application, these responsibilities add ongoing security work that competes with other product priorities.&lt;/p&gt;

&lt;p&gt;This is where passwordless authentication becomes useful. Passkeys remove the need to remember and type a reusable password, reducing exposure to common password-related attacks.&lt;/p&gt;

&lt;p&gt;They don't eliminate every authentication risk, though. Account recovery, session security, authorization, and fallback methods still need careful design. The goal is to simplify sign-in without compromising the security of the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Passwordless Authentication Works
&lt;/h2&gt;

&lt;p&gt;Passwordless authentication describes a login experience that doesn't require the user to enter a conventional password. There are several ways to achieve this, but passkeys are a useful starting point because they combine a straightforward user experience with public-key cryptography.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passkeys: Prove Your Identity Without Typing a Password
&lt;/h3&gt;

&lt;p&gt;When a user registers a passkey, their authenticator creates a public/private key pair. The private key is protected by the authenticator or passkey provider, while the identity provider stores the corresponding public-key credential.&lt;/p&gt;

&lt;p&gt;During sign-in, the identity provider sends a challenge. The authenticator responds using the private key, and the identity provider verifies the response. If authentication succeeds, the user can continue into the application.&lt;/p&gt;

&lt;p&gt;The browser handles this interaction through &lt;strong&gt;WebAuthn&lt;/strong&gt;, a web standard for public-key authentication. &lt;/p&gt;

&lt;p&gt;Depending on the device, users may confirm their identity with Face ID, Touch ID, Windows Hello, a device PIN, or a compatible security key. Their biometric data isn't sent to the application as part of the WebAuthn exchange.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   ┌──────────────────────────────┐
                   │       Sign in / Register     │
                   │                              │
                   │  Enter username or email     │
                   │  Choose Register             │
                   └──────────────┬───────────────┘
                                  │
                                  ▼
                   ┌──────────────────────────────┐
                   │          Register            │
                   │                              │
                   │  Username: hadil             │
                   │  Email: hadil@example.com    │
                   │                              │
                   │       [ Register ]           │
                   └──────────────┬───────────────┘
                                  │
                                  ▼
                   ┌──────────────────────────────┐
                   │      Choose Setup Method     │
                   │                              │
                   │      [ Setup Password ]      │
                   │             OR               │
                   │      [ Setup Passkey ]       │
                   └──────────────┬───────────────┘
                                  │
                 ┌────────────────┴────────────────┐
                 │                                 │
                 ▼                                 ▼
    ┌────────────────────────┐       ┌────────────────────────┐
    │     Setup Password     │       │      Setup Passkey     │
    └────────────┬───────────┘       └────────────┬───────────┘
                 │                                 │
                 ▼                                 ▼
    ┌────────────────────────┐       ┌────────────────────────┐
    │ Enter a new password   │       │ Register a passkey     │
    │ Confirm the password   │       │ with your device       │
    │                        │       │                        │
    │     [ Register ]       │       │     [ Continue ]       │
    └────────────┬───────────┘       └────────────┬───────────┘
                 │                                 │
                 │                                 ▼
                 │                    ┌────────────────────────┐
                 │                    │  Choose authenticator  │
                 │                    │                        │
                 │                    │  • Windows Hello       │
                 │                    │  • Touch ID / Face ID  │
                 │                    │  • Security key        │
                 │                    └────────────┬───────────┘
                 │                                 │
                 │                                 ▼
                 │                    ┌────────────────────────┐
                 │                    │ Confirm registration   │
                 │                    │ with device PIN,       │
                 │                    │ fingerprint or face    │
                 │                    └────────────┬───────────┘
                 │                                 │
                 └────────────────┬────────────────┘
                                  │
                                  ▼
                   ┌──────────────────────────────┐
                   │    Registration Complete     │
                   │                              │
                   │  User can sign in using the  │
                   │  configured authentication   │
                   │  method.                     │
                   └──────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;This is a conceptual registration flow. The available authentication methods and registration steps depend on the application's identity provider and configured authentication flow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For developers, passkeys still require configuration: users need a way to register credentials, the identity provider must accept them, and the application must establish a secure session after authentication.&lt;/p&gt;
&lt;h3&gt;
  
  
  Magic Links: A Different Way to Skip Passwords
&lt;/h3&gt;

&lt;p&gt;Magic links offer another passwordless approach. The user enters an email address, receives a login link, and follows it to authenticate. The link typically contains a time-limited or one-time token that must be validated securely.&lt;/p&gt;

&lt;p&gt;This can make onboarding straightforward because users don't have to create or remember a password. However, the experience depends on email delivery and on the security of the user's email account. Developers must also protect against token reuse, link leakage, and unsafe redirect handling.&lt;/p&gt;
&lt;h3&gt;
  
  
  Where Does Keycloak Fit Into the Flow?
&lt;/h3&gt;

&lt;p&gt;Keycloak can manage authentication, user credentials, and the login flows that applications use through standard identity protocols. With passwordless authentication configured, it can verify a registered passkey and complete the authentication flow for the application.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              ┌─────────────────────────────┐
              │            User             │
              │                             │
              │      Clicks "Sign in"       │
              └──────────────┬──────────────┘
                             │
                             ▼
              ┌─────────────────────────────┐
              │       Web Application       │
              │                             │
              │  React / Next.js / other    │
              │  application                │
              └──────────────┬──────────────┘
                             │
                             │ Redirects for login
                             ▼
              ┌─────────────────────────────┐
              │          Keycloak           │
              │                             │
              │  Identity and authentication│
              │  Handles the configured     │
              │  login flow                 │
              └──────────────┬──────────────┘
                             │
                 ┌───────────┴───────────┐
                 │                       │
                 ▼                       ▼
       ┌───────────────────┐   ┌───────────────────┐
       │ Password          │   │ Passkey           │
       │ authentication    │   │ authentication    │
       │                   │   │                   │
       │ Enter credentials │   │ Use device        │
       │                   │   │ authenticator     │
       └─────────┬─────────┘   └─────────┬─────────┘
                 │                       │
                 └───────────┬───────────┘
                             │
                             ▼
             ┌───────────────────────────────┐
             │   Keycloak Verifies Login     │
             │                               │
             │ Applies configured policies   │
             │ and completes authentication  │
             └───────────────┬───────────────┘
                             │
                             ▼
              ┌─────────────────────────────┐
              │       OIDC Response         │
              │                             │
              │  Application receives the   │
              │  authorization code and     │
              │  completes the OIDC flow    │
              └──────────────┬──────────────┘
                             │
                             ▼
              ┌─────────────────────────────┐
              │       Web Application       │
              │                             │
              │  Establishes its session    │
              │  and checks authorization   │
              └──────────────┬──────────────┘
                             │
                             ▼
              ┌─────────────────────────────┐
              │     Protected Resource      │
              │                             │
              │       Access granted        │
              └─────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Developers can use an identity provider to manage the authentication process without having to build every part of credential registration and verification themselves. The application still needs to integrate correctly with the identity provider and handle its own authenticated sessions and authorization.&lt;/p&gt;


&lt;h2&gt;
  
  
  Passkeys vs. Passwords vs. MFA: What Changes?
&lt;/h2&gt;

&lt;p&gt;These terms often appear together in authentication discussions, but they describe different things. Understanding the distinction helps you choose the right login flow for your application.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What the user does&lt;/th&gt;
&lt;th&gt;What it provides&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Password-based login&lt;/td&gt;
&lt;td&gt;Enters a username and password&lt;/td&gt;
&lt;td&gt;Authentication using a memorized secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passwordless passkey login&lt;/td&gt;
&lt;td&gt;Uses a registered passkey, often with a device unlock or security key&lt;/td&gt;
&lt;td&gt;Authentication using public-key cryptography without entering a password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-factor authentication (MFA)&lt;/td&gt;
&lt;td&gt;Completes multiple authentication factors according to the configured policy&lt;/td&gt;
&lt;td&gt;An additional layer of account protection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A passkey can replace a password as the primary authentication method, while MFA requires multiple authentication factors according to the configured policy. The two can also work together: passkeys can support passwordless login or be incorporated into a multi-factor flow.&lt;/p&gt;

&lt;p&gt;Passkeys offer strong phishing resistance because WebAuthn credentials are associated with the website's identity. A credential registered for one website can't simply be reused on an unrelated fake domain.&lt;/p&gt;

&lt;p&gt;For developers, the right approach depends on the application's security requirements, its users' devices, and the available account recovery options.&lt;/p&gt;


&lt;h2&gt;
  
  
  Where Skycloak Comes In
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://skycloak.io/" rel="noopener noreferrer"&gt;Skycloak&lt;/a&gt; provides managed Keycloak, allowing developers to use Keycloak's identity and authentication capabilities without managing the underlying identity infrastructure themselves.&lt;/p&gt;

&lt;p&gt;It includes a &lt;a href="https://skycloak.io/docs/tutorials/implementing-magic-links/" rel="noopener noreferrer"&gt;passkey configuration recipe&lt;/a&gt; for enabling &lt;a href="https://skycloak.io/features/passwordless/" rel="noopener noreferrer"&gt;passwordless&lt;/a&gt; registration and creating a dedicated &lt;code&gt;browser-passkey&lt;/code&gt; authentication flow. The documented setup also describes a password-based fallback for users who haven't registered a passkey.&lt;/p&gt;

&lt;p&gt;This configuration provides a starting point for exploring passkey authentication with Keycloak.&lt;/p&gt;

&lt;p&gt;For current pricing and plan details, visit the &lt;a href="https://skycloak.io/pricing/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=hadil_passwords" rel="noopener noreferrer"&gt;Skycloak pricing page&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Using Skycloak for Passwordless Authentication With Passkeys
&lt;/h2&gt;

&lt;p&gt;Passkeys change how users authenticate, but an application still needs an identity provider to manage registration, verify authentication, and handle the login flow. Skycloak provides managed Keycloak and a preconfigured Passkeys recipe that helps developers set up this flow without building a custom WebAuthn authenticator.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the Skycloak Passkeys Recipe Configures
&lt;/h3&gt;

&lt;p&gt;Skycloak's Passkeys recipe applies a passkey configuration to a selected Keycloak realm. It handles three main parts of the setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Passkey registration:&lt;/strong&gt; Enables the &lt;code&gt;webauthn-register-passwordless&lt;/code&gt; required action so users can register a passkey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A dedicated authentication flow:&lt;/strong&gt; Creates a &lt;code&gt;browser-passkey&lt;/code&gt; flow that identifies the user first and then prompts them to authenticate with a passkey.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback authentication:&lt;/strong&gt; Keeps password authentication and conditional OTP available for users who haven't registered a passkey, according to the configured flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The recipe leaves the existing &lt;code&gt;browser&lt;/code&gt; flow untouched. It also provides an option to require passkey registration for existing users, so developers can choose when to enforce the change across a realm.&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%2F77kiutbr4g0qpjis4guo.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%2F77kiutbr4g0qpjis4guo.png" alt="Skycloak Recipes page showing the available Passkeys configuration for a Keycloak realm" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;
Skycloak's Recipes section includes a Passkeys configuration that can be applied to a selected realm
&amp;nbsp;
&lt;h3&gt;
  
  
  Prepare Your Development Environment
&lt;/h3&gt;

&lt;p&gt;Start with a dedicated realm for your test application. Keeping the setup separate makes it easier to configure the authentication flow and test registration and sign-in without affecting other applications or users.&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%2Fn7xsjkeqjarf1xt1i0s0.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%2Fn7xsjkeqjarf1xt1i0s0.png" alt="Skycloak dashboard showing the first-app realm" width="800" height="757"&gt;&lt;/a&gt;&lt;/p&gt;
I created my first-app realm in the Skycloak dashboard
&amp;nbsp;

&lt;p&gt;You'll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity provider:&lt;/strong&gt; A Skycloak-managed Keycloak environment with a development realm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application:&lt;/strong&gt; A small React or Next.js application with an OpenID Connect (OIDC) integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser and authenticator:&lt;/strong&gt; A WebAuthn-compatible browser and a supported authenticator, such as Windows Hello, Touch ID, or a security key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test account:&lt;/strong&gt; A dedicated user account for trying passkey registration and sign-in.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Connect the Application Through OIDC
&lt;/h3&gt;

&lt;p&gt;The application needs an OIDC client in Keycloak so it can redirect users to the identity provider for authentication and receive the appropriate authentication response.&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%2Fel2eue6bytrmq5otedlz.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%2Fel2eue6bytrmq5otedlz.png" alt="Keycloak Create client screen with OpenID Connect selected" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;
Creating an OpenID Connect client in Keycloak is an early step in connecting the application to its identity provider
&amp;nbsp;

&lt;p&gt;Configure the client's redirect URIs and other settings to match your application. Skycloak's &lt;a href="https://skycloak.io/docs/tutorials/first-application-setup/" rel="noopener noreferrer"&gt;first application setup guide&lt;/a&gt; provides guidance for creating the client.&lt;/p&gt;

&lt;p&gt;Your application will also need the relevant issuer URL and client ID for its OIDC integration. Keep client secrets out of browser-side code, and use HTTPS in production.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure and Test Passkey Authentication
&lt;/h3&gt;

&lt;p&gt;With the realm and OIDC client in place, follow Skycloak's &lt;a href="https://skycloak.io/docs/tutorials/implementing-magic-links/" rel="noopener noreferrer"&gt;Passkey configuration guide&lt;/a&gt; to apply the recipe and understand the resulting authentication flow.&lt;/p&gt;

&lt;p&gt;Work through these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Apply the Passkeys recipe.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Select your development realm and follow the documented instructions to enable passkey registration and create the &lt;code&gt;browser-passkey&lt;/code&gt; flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Connect your application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Configure the application's OIDC integration with the correct issuer URL, client ID, and redirect URI. The application should use the identity provider's authentication flow and handle the OIDC response according to its integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Register a passkey.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sign in with your test account and follow the configured registration flow. The exact screens depend on the realm's configuration and the user's authentication state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Test the sign-in flow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try signing in with the registered passkey using a compatible browser and authenticator. Also check the configured fallback for users who haven't registered a passkey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Check recovery and failure scenarios.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Test what happens when a user cancels the browser prompt, has no registered passkey, or loses access to their authenticator. Confirm that the available fallback and recovery options work as intended.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Developers Still Need to Handle
&lt;/h3&gt;

&lt;p&gt;The recipe configures the identity-provider side of passkey authentication, but it doesn't remove the application's integration responsibilities. Developers still need to handle OIDC correctly, establish and protect application sessions, enforce authorization, and configure redirect URIs securely.&lt;/p&gt;

&lt;p&gt;Before using the flow in production, test it across the browsers and devices your users rely on, and decide whether passkey registration should remain optional or become a requirement for the realm.&lt;/p&gt;


&lt;h2&gt;
  
  
  Edge Cases to Test Before Shipping
&lt;/h2&gt;

&lt;p&gt;A passkey login that works once isn't enough for production. Developers need to consider recovery, device compatibility, and authentication failures before making passwordless authentication the default.&lt;/p&gt;

&lt;p&gt;Account recovery is a priority. Users may lose a device or lose access to their authenticator. Provide a secure recovery process that helps legitimate users regain access without creating an easy route for attackers.&lt;/p&gt;

&lt;p&gt;Test different browsers, operating systems, and authenticators relevant to your audience. Also check what happens when users cancel the passkey prompt, haven't registered a passkey, or try to access a protected page without an authenticated session.&lt;/p&gt;

&lt;p&gt;Finally, remember that passkeys don't replace authorization checks, secure session handling, or session expiration policies. Authentication verifies a user's identity; the application still determines what they can access.&lt;/p&gt;

&lt;p&gt;Before shipping, use this checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] New users can register a passkey successfully.&lt;/li&gt;
&lt;li&gt;[ ] Returning users can sign in with a registered passkey.&lt;/li&gt;
&lt;li&gt;[ ] Users have a documented, secure account recovery process.&lt;/li&gt;
&lt;li&gt;[ ] Unsupported or cancelled authentication attempts are handled gracefully.&lt;/li&gt;
&lt;li&gt;[ ] Unauthenticated users cannot access protected pages.&lt;/li&gt;
&lt;li&gt;[ ] Redirect URLs, sessions, and identity-provider settings are configured securely.&lt;/li&gt;
&lt;li&gt;[ ] Relevant browser and device combinations have been tested.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is passwordless authentication?
&lt;/h3&gt;

&lt;p&gt;→ Passwordless authentication allows users to sign in without entering a conventional password. It can use passkeys, security keys, magic links, or other password-free methods. Passkeys use public-key cryptography and can provide phishing-resistant authentication when correctly implemented.&lt;/p&gt;
&lt;h3&gt;
  
  
  How do passkeys work without a password?
&lt;/h3&gt;

&lt;p&gt;→ A passkey uses a public/private key pair associated with the relying party. During authentication, the authenticator uses the private key to respond to a challenge, and the identity provider verifies the response with the registered public key. The user doesn't need to enter a conventional password.&lt;/p&gt;
&lt;h3&gt;
  
  
  Are passkeys the same as MFA?
&lt;/h3&gt;

&lt;p&gt;→ No. Passwordless authentication describes how a user signs in without a conventional password. MFA requires multiple authentication factors according to the configured policy. A passkey can be used for passwordless login or incorporated into a multi-factor authentication flow.&lt;/p&gt;
&lt;h3&gt;
  
  
  What happens if a user loses their passkey?
&lt;/h3&gt;

&lt;p&gt;→ The user needs a supported recovery path, such as another registered passkey or a secure account recovery process. The appropriate approach depends on the application's identity configuration. Developers should plan recovery before making passkeys the only available authentication method.&lt;/p&gt;
&lt;h3&gt;
  
  
  Is passwordless authentication more secure than passwords?
&lt;/h3&gt;

&lt;p&gt;→ Passkeys can offer important security advantages over passwords, including resistance to common phishing attacks and the absence of a reusable password that can be stolen and replayed. The overall security of the application still depends on account recovery, session management, authorization, and correct implementation.&lt;/p&gt;


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

&lt;p&gt;Passwordless authentication can simplify sign-in and reduce reliance on conventional passwords. &lt;/p&gt;

&lt;p&gt;Passkeys offer a phishing-resistant approach, but a production-ready implementation still needs secure registration, account recovery, device compatibility, session handling, and authorization.&lt;/p&gt;

&lt;p&gt;Managed Keycloak can reduce the burden of operating identity infrastructure. &lt;/p&gt;

&lt;p&gt;Skycloak's passkey configuration gives developers a starting point for exploring this approach, while OIDC connects the identity provider to the application.&lt;/p&gt;

&lt;p&gt;The goal isn't just to remove a password field. It's to make authentication easier for users without compromising security.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>programming</category>
      <category>security</category>
      <category>webdev</category>
      <category>development</category>
    </item>
    <item>
      <title>Your Marketing Site Has 40 Scripts. Which Ones Are Actually Worth Keeping?</title>
      <dc:creator>Hadil Ben Abdallah</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:09:59 +0000</pubDate>
      <link>https://dev.to/yassersoliman/your-marketing-site-has-40-scripts-which-ones-are-actually-worth-keeping-1kp</link>
      <guid>https://dev.to/yassersoliman/your-marketing-site-has-40-scripts-which-ones-are-actually-worth-keeping-1kp</guid>
      <description>&lt;p&gt;Third-party scripts are easy to accumulate on a marketing website. A site might start with GA4 for analytics, a cookie banner, and a chat widget.&lt;/p&gt;

&lt;p&gt;A year or two later, the list can look very different.&lt;/p&gt;

&lt;p&gt;There’s a tag manager, heatmaps, session recordings, A/B testing, ad pixels, a CRM integration, a chatbot, a scheduling tool, a consent platform, embedded videos, social widgets, product analytics, and other tools.&lt;/p&gt;

&lt;p&gt;Each one had a reason to exist.&lt;/p&gt;

&lt;p&gt;The problem is that the browser doesn't care why you added it.&lt;/p&gt;

&lt;p&gt;It has to download, parse, and execute that code on a real visitor's device. Some third-party scripts consume CPU, compete for network resources, delay other work, or add work to the main thread. Chrome's performance guidance specifically calls out third-party code as a significant source of page-load and JavaScript costs.&lt;/p&gt;

&lt;p&gt;And that creates a problem that has very little to do with whether your marketing team &lt;em&gt;likes&lt;/em&gt; a particular tool.&lt;/p&gt;

&lt;p&gt;The question is whether the tool still earns its place on the website.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Keep a third-party script when it has a clear business purpose, an identifiable owner, useful data or functionality, and a cost that makes sense for the pages where it runs.&lt;/p&gt;

&lt;p&gt;Remove it when nobody can explain why it exists, nobody uses the data it collects, another tool already does the same job, or its performance and maintenance cost are greater than its value.&lt;/p&gt;

&lt;p&gt;A practical way to evaluate every script is to ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What does this script do?&lt;/li&gt;
&lt;li&gt;Who actually uses what it provides?&lt;/li&gt;
&lt;li&gt;Does it affect leads, conversions, analytics, customer experience, or another measurable business outcome?&lt;/li&gt;
&lt;li&gt;Does another tool already cover the same job?&lt;/li&gt;
&lt;li&gt;Does it need to load on every page?&lt;/li&gt;
&lt;li&gt;What does it cost in performance, privacy, maintenance, and reliability?&lt;/li&gt;
&lt;li&gt;Who owns it?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you cannot answer those questions, the script deserves an audit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Too Many Third-Party Scripts Become a Problem
&lt;/h2&gt;

&lt;p&gt;Third-party code is common on modern marketing websites. Analytics platforms, advertising tools, chat systems, consent management, testing platforms, embedded content, and other services often depend on JavaScript loaded from an external domain.&lt;/p&gt;

&lt;p&gt;That doesn't automatically make them bad.&lt;/p&gt;

&lt;p&gt;A script that sends important conversion data to your analytics platform can be worth its cost. A consent-management platform may be essential for how your site handles tracking. A scheduling widget may directly support your sales process.&lt;/p&gt;

&lt;p&gt;The problem starts when the list grows without anyone reviewing it.&lt;/p&gt;

&lt;p&gt;A marketer adds a new tool for a campaign. A developer installs its snippet. Another team adds a heatmap tool six months later. A redesign introduces a second analytics implementation. An agency adds its own tracking script. The campaign ends, but the script stays.&lt;/p&gt;

&lt;p&gt;Nothing looks broken.&lt;/p&gt;

&lt;p&gt;The website still loads. The forms still work. The analytics dashboard still has numbers in it.&lt;/p&gt;

&lt;p&gt;Meanwhile, the browser is doing more work every time someone visits the site.&lt;/p&gt;

&lt;p&gt;Chrome's Lighthouse documentation notes that third-party scripts can significantly affect page performance, including the amount of work performed on the browser's main thread.&lt;/p&gt;

&lt;p&gt;That matters even more on marketing websites because the third-party script list often grows through small, reasonable decisions rather than one obviously bad technical choice.&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;script bloat&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And script bloat is difficult to spot when you look at each tool separately.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Find Every Third-Party Script on Your Website
&lt;/h2&gt;

&lt;p&gt;Before deciding what stays and what goes, you need a complete inventory.&lt;/p&gt;

&lt;p&gt;This sounds simple until you actually do it.&lt;/p&gt;

&lt;p&gt;A script can be added directly to a page, injected through Google Tag Manager, loaded by a WordPress plugin, included by a Webflow integration, or introduced by another third-party tool. Looking at the page source alone may give you an incomplete picture.&lt;/p&gt;

&lt;p&gt;For a proper audit, I would check the website from several angles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with the browser
&lt;/h3&gt;

&lt;p&gt;Open Chrome DevTools and go to &lt;strong&gt;Network&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Reload the page with the Network panel open, then filter by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Fetch/XHR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Img&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Doc&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The JavaScript filter is the obvious starting point, but don't stop there. A third-party tool may load JavaScript and then make additional requests through XHR or fetch.&lt;/p&gt;

&lt;p&gt;Look at the domains making those requests.&lt;/p&gt;

&lt;p&gt;You might find something you recognize immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;www.googletagmanager.com
www.google-analytics.com
connect.facebook.net
snap.licdn.com
static.hotjar.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You may also find domains that mean nothing to you.&lt;/p&gt;

&lt;p&gt;Those deserve investigation.&lt;/p&gt;

&lt;p&gt;The goal at this stage isn't to decide whether a script is good or bad. You're building the inventory first.&lt;/p&gt;
&lt;h3&gt;
  
  
  Check your tag manager
&lt;/h3&gt;

&lt;p&gt;If the site uses Google Tag Manager, open the container and review every tag.&lt;/p&gt;

&lt;p&gt;Pay attention to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tags that are still active&lt;/li&gt;
&lt;li&gt;tags with unclear names&lt;/li&gt;
&lt;li&gt;old campaign tags&lt;/li&gt;
&lt;li&gt;duplicate analytics tags&lt;/li&gt;
&lt;li&gt;tags firing on every page&lt;/li&gt;
&lt;li&gt;tags that were created for a temporary campaign&lt;/li&gt;
&lt;li&gt;tags owned by former employees or agencies&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Check your CMS and plugins
&lt;/h3&gt;

&lt;p&gt;If the website runs on WordPress or another CMS with integrations and plugins, check those too.&lt;/p&gt;

&lt;p&gt;A plugin may inject tracking code without anyone adding a script manually.&lt;/p&gt;

&lt;p&gt;This is one reason script audits should include the systems responsible for &lt;strong&gt;adding&lt;/strong&gt; code, not just the code itself.&lt;/p&gt;

&lt;p&gt;You may discover that the same service is being loaded through two different paths.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;GA4 is configured directly in the CMS&lt;/li&gt;
&lt;li&gt;another GA4 implementation exists in GTM&lt;/li&gt;
&lt;li&gt;a plugin adds another tracking library&lt;/li&gt;
&lt;li&gt;a custom script sends additional events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result can be duplicate data and unnecessary browser work at the same time.&lt;/p&gt;


&lt;h2&gt;
  
  
  Measure the Cost of Third-Party Scripts
&lt;/h2&gt;

&lt;p&gt;Once you have the inventory, measure the actual impact.&lt;/p&gt;

&lt;p&gt;This is where Chrome DevTools and Lighthouse become useful. Core Web Vitals can also help you understand how performance issues affect the actual experience of visitors.&lt;/p&gt;

&lt;p&gt;Lighthouse has a dedicated third-party summary that helps identify third-party resources and the amount of main-thread work associated with them.&lt;/p&gt;

&lt;p&gt;You can also use Chrome DevTools to inspect individual requests and understand what happens when the page loads.&lt;/p&gt;

&lt;p&gt;Look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;request count&lt;/li&gt;
&lt;li&gt;transferred size&lt;/li&gt;
&lt;li&gt;resource size&lt;/li&gt;
&lt;li&gt;loading time&lt;/li&gt;
&lt;li&gt;JavaScript execution&lt;/li&gt;
&lt;li&gt;main-thread activity&lt;/li&gt;
&lt;li&gt;additional network requests&lt;/li&gt;
&lt;li&gt;when the resource starts loading&lt;/li&gt;
&lt;li&gt;whether it blocks or delays important work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't obsess over one number.&lt;/p&gt;

&lt;p&gt;A 200 KB script isn't automatically worse than a 50 KB script. The smaller script could trigger several additional requests or perform expensive JavaScript work after it loads.&lt;/p&gt;

&lt;p&gt;Likewise, a script that takes a little time to load may still provide significant business value.&lt;/p&gt;

&lt;p&gt;The broader impact of website speed also matters when evaluating third-party code, especially on marketing sites where performance directly affects the user experience.&lt;/p&gt;

&lt;p&gt;You're looking for the &lt;strong&gt;cost-to-value ratio&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Look for Duplicate Functionality
&lt;/h2&gt;

&lt;p&gt;One of the easiest wins in a script audit is finding tools that overlap.&lt;/p&gt;

&lt;p&gt;A growing marketing stack can accumulate several tools that solve almost the same problem.&lt;/p&gt;

&lt;p&gt;For example, you might have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GA4 for analytics&lt;/li&gt;
&lt;li&gt;another product analytics platform&lt;/li&gt;
&lt;li&gt;a heatmap tool&lt;/li&gt;
&lt;li&gt;a session-recording tool&lt;/li&gt;
&lt;li&gt;a CRO platform&lt;/li&gt;
&lt;li&gt;a separate event-tracking solution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They aren't identical, but there may be significant overlap.&lt;/p&gt;

&lt;p&gt;The same thing can happen with tracking.&lt;/p&gt;

&lt;p&gt;You might find multiple systems tracking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page views&lt;/li&gt;
&lt;li&gt;form submissions&lt;/li&gt;
&lt;li&gt;CTA clicks&lt;/li&gt;
&lt;li&gt;video plays&lt;/li&gt;
&lt;li&gt;conversions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That creates two problems.&lt;/p&gt;

&lt;p&gt;First, you're paying for tools that may not all be necessary.&lt;/p&gt;

&lt;p&gt;Second, your team can end up with several versions of the same event and different numbers in different dashboards.&lt;/p&gt;

&lt;p&gt;That kind of inconsistency can make analytics harder to trust, especially when multiple tracking systems are collecting similar data.&lt;/p&gt;

&lt;p&gt;The technical cleanup can be easy.&lt;/p&gt;

&lt;p&gt;The organizational cleanup is usually harder.&lt;/p&gt;

&lt;p&gt;Someone needs to decide which system is the source of truth for each type of data.&lt;/p&gt;


&lt;h2&gt;
  
  
  Do Third-Party Scripts Need to Load on Every Page?
&lt;/h2&gt;

&lt;p&gt;This is one of the highest-value questions in the entire audit.&lt;/p&gt;

&lt;p&gt;A tool can be useful without needing site-wide access.&lt;/p&gt;

&lt;p&gt;Consider a scheduling widget.&lt;/p&gt;

&lt;p&gt;If its only purpose is to let visitors book a call, loading it on every blog article may not make sense.&lt;/p&gt;

&lt;p&gt;The same applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calculators&lt;/li&gt;
&lt;li&gt;interactive demos&lt;/li&gt;
&lt;li&gt;chat tools&lt;/li&gt;
&lt;li&gt;review widgets&lt;/li&gt;
&lt;li&gt;embedded videos&lt;/li&gt;
&lt;li&gt;campaign-specific tracking&lt;/li&gt;
&lt;li&gt;product-specific functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple rule is useful here:&lt;/p&gt;

&lt;p&gt;If a script only supports one type of page, try to load it only where that functionality is needed.&lt;/p&gt;

&lt;p&gt;This can reduce unnecessary requests and JavaScript execution on pages that don't benefit from the tool.&lt;/p&gt;

&lt;p&gt;It also makes the website easier to reason about.&lt;/p&gt;

&lt;p&gt;When someone investigates a slow blog post six months from now, they won't have to wonder why it is loading a collection of sales and product widgets that have nothing to do with the article.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Script Audit Should End With a Decision
&lt;/h2&gt;

&lt;p&gt;Once you've collected the data, every script should have a clear status.&lt;/p&gt;

&lt;p&gt;I like using five:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Keep&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The script provides meaningful business value, and its cost is justified.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Optimize&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The tool is valuable, but its loading behavior, implementation, or scope can be improved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Restrict&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The tool is useful only on certain pages, for certain users, or after a specific interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Replace&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The business needs the functionality, but another implementation may provide a better balance of functionality, reliability, and performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Remove&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Nobody needs it, nobody owns it, or its value doesn't justify keeping it.&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%2Fjzixo7acabnvokz7bhvy.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%2Fjzixo7acabnvokz7bhvy.png" alt="Each script should have a clear status, a reason, an owner, and an appropriate place in your user journey" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That final category is often smaller than people expect.&lt;/p&gt;

&lt;p&gt;The goal of a good audit isn't to delete half the website.&lt;/p&gt;

&lt;p&gt;It's to make sure every piece of third-party code has a reason, an owner, and an appropriate place in the user journey.&lt;/p&gt;


&lt;h2&gt;
  
  
  Consent Changes the Loading Strategy
&lt;/h2&gt;

&lt;p&gt;Privacy and consent requirements add another layer to script management.&lt;/p&gt;

&lt;p&gt;Not every tracking or marketing script should necessarily load in the same way for every visitor.&lt;/p&gt;

&lt;p&gt;Depending on the jurisdiction, consent configuration, and purpose of the technology, some third-party scripts may need to wait until the appropriate consent has been given. Google's &lt;a href="https://developers.google.com/analytics/devguides/collection/ga4" rel="noopener noreferrer"&gt;Consent Mode documentation&lt;/a&gt; explains how Google tags can adjust their behavior based on a user's consent choices.&lt;/p&gt;

&lt;p&gt;That means your audit should document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which scripts are strictly necessary&lt;/li&gt;
&lt;li&gt;which require consent&lt;/li&gt;
&lt;li&gt;what happens when consent is denied&lt;/li&gt;
&lt;li&gt;whether the consent platform actually controls the scripts&lt;/li&gt;
&lt;li&gt;whether tags can fire before the expected consent state&lt;/li&gt;
&lt;li&gt;whether the implementation matches your organization's privacy requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is another reason you shouldn't simply copy a list of scripts from one website to another.&lt;/p&gt;

&lt;p&gt;The technical implementation and the privacy requirements need to be considered together.&lt;/p&gt;

&lt;p&gt;A consent banner that exists visually while tracking scripts continue firing before the appropriate consent state isn't solving the underlying problem.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Goal Isn't Fewer Scripts. It's a Website You Can Explain.
&lt;/h2&gt;

&lt;p&gt;A marketing website can have dozens of integrations and still be well managed.&lt;/p&gt;

&lt;p&gt;The problem isn't the number sitting in your inventory.&lt;/p&gt;

&lt;p&gt;The problem is when nobody can explain what those scripts do, why they load, who owns them, or what would happen if they disappeared.&lt;/p&gt;

&lt;p&gt;That's when your marketing stack starts becoming technical debt.&lt;/p&gt;

&lt;p&gt;A good WebOps process gives every integration a purpose and a place.&lt;/p&gt;

&lt;p&gt;It also gives the team a way to challenge old decisions.&lt;/p&gt;

&lt;p&gt;A tool that made perfect sense two years ago may not make sense today. A campaign may have ended. A new platform may have replaced an old one. A feature may have moved into another part of the stack.&lt;/p&gt;

&lt;p&gt;The website should evolve with those changes.&lt;/p&gt;

&lt;p&gt;And that brings us to the simplest rule I use for third-party scripts:&lt;/p&gt;

&lt;p&gt;If you can't explain the value, the owner, the scope, and the cost, it's time to investigate why the script is still there.&lt;/p&gt;


&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;
&lt;h3&gt;
  
  
  How many third-party scripts should a marketing website have?
&lt;/h3&gt;

&lt;p&gt;→ There is no universal number that defines a healthy website.&lt;/p&gt;

&lt;p&gt;A site with 10 scripts can have serious performance or tracking problems, while another site with 30 or 40 can be well managed.&lt;/p&gt;

&lt;p&gt;What matters is whether each script has a clear purpose, an owner, an appropriate loading scope, and a reasonable technical cost.&lt;/p&gt;

&lt;p&gt;Focus on understanding and controlling the script stack instead of chasing a specific number.&lt;/p&gt;
&lt;h3&gt;
  
  
  Do third-party scripts slow down a website?
&lt;/h3&gt;

&lt;p&gt;→ They can. Third-party scripts can add network requests, download JavaScript, consume CPU, execute code on the main thread, and trigger additional resources.&lt;/p&gt;

&lt;p&gt;The actual impact depends on the service, how it is implemented, when it loads, and what it does after loading.&lt;/p&gt;

&lt;p&gt;Tools such as Chrome DevTools and Lighthouse can help you identify which third-party resources are contributing to the work performed by the browser.&lt;/p&gt;
&lt;h3&gt;
  
  
  Should I remove Google Tag Manager to improve website performance?
&lt;/h3&gt;

&lt;p&gt;→ Not automatically. Google Tag Manager is a container that can load many different tags, so the performance impact depends heavily on what you put inside it.&lt;/p&gt;

&lt;p&gt;Removing GTM while leaving the underlying tracking requirements unresolved may simply move the problem somewhere else.&lt;/p&gt;

&lt;p&gt;Audit the tags inside the container first. Remove unused tags, eliminate duplicate tracking, restrict tags to relevant pages, and review how non-critical tags are loaded.&lt;/p&gt;
&lt;h3&gt;
  
  
  Should every marketing script load on every page?
&lt;/h3&gt;

&lt;p&gt;→ No. A script should generally load wherever its functionality or measurement is actually needed.&lt;/p&gt;

&lt;p&gt;A scheduling tool may only be necessary on pages where visitors can book a meeting. A product demo widget may only belong on product pages. A campaign-specific tracking script may only be relevant during a particular campaign.&lt;/p&gt;

&lt;p&gt;Reducing unnecessary site-wide loading can improve performance while keeping the functionality your marketing team actually needs.&lt;/p&gt;
&lt;h3&gt;
  
  
  How often should I audit third-party scripts?
&lt;/h3&gt;

&lt;p&gt;→ For many B2B SaaS websites, a quarterly review is a sensible starting point.&lt;/p&gt;

&lt;p&gt;You should also review the script inventory after major website changes, migrations, new marketing tools, tracking architecture changes, or campaigns that introduce temporary integrations.&lt;/p&gt;

&lt;p&gt;The exact frequency depends on how quickly the website and marketing stack change.&lt;/p&gt;


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

&lt;p&gt;Having less scripts in your marketing site shouldn’t be just a goal in itself. Your site must utilize a technology stack that your marketing team is familiar with and can justify. &lt;/p&gt;

&lt;p&gt;Each and every third-party script must justify its right to exist through efficiency of its business function, prevail scope, and the known owner. &lt;/p&gt;

&lt;p&gt;Next time you find dozens of third-party requests present in DevTools, don’t ask yourself how to get rid of them. Instead, try to find out which requests actually has the right to exist.&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thanks for reading! 🙏🏻 &lt;br&gt; I hope you found this useful ✅ &lt;br&gt; Please react and follow for more 😍 &lt;br&gt; Made with 💙 by &lt;a href="https://dev.to/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;a href="https://www.linkedin.com/in/hadil-ben-abdallah/" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fu48q29oef3l4a6eow30h.png" alt="LinkedIn" width="40" height="40"&gt;&lt;/a&gt; &lt;a href="https://github.com/Hadil-Ben-Abdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Fhuvszgj6eun7xfvnwv51.png" alt="GitHub" width="50" height="50"&gt;&lt;/a&gt; &lt;a href="https://x.com/hadilbnabdallah" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F53x550t83v5ner74xkxo.jpg" alt="Twitter" width="40" height="40"&gt;&lt;/a&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="ltag__user ltag__user__id__1209000"&gt;
    &lt;a href="/hadil" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/hadil"&gt;Hadil Ben Abdallah&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/hadil"&gt;Software Engineer • Technical Writer (300K+ readers &amp;amp; 25K+ followers) • Trusted by 20+ startups and tech companies worldwide
I turn brands into websites people 💙 to use&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



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