<?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: Mahmoud 🦀</title>
    <description>The latest articles on DEV Community by Mahmoud 🦀 (@wiseai).</description>
    <link>https://dev.to/wiseai</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%2F827951%2F8d69ab6e-a28d-4d13-9652-bdd2f5eb90f8.png</url>
      <title>DEV Community: Mahmoud 🦀</title>
      <link>https://dev.to/wiseai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wiseai"/>
    <language>en</language>
    <item>
      <title>No, Seriously. Neural Networks Cannot Produce Genuine Intelligence.</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 11 Oct 2026 05:36:17 +0000</pubDate>
      <link>https://dev.to/wiseai/no-seriously-neural-networks-cannot-produce-genuine-intelligence-4l39</link>
      <guid>https://dev.to/wiseai/no-seriously-neural-networks-cannot-produce-genuine-intelligence-4l39</guid>
      <description>&lt;p&gt;Hey everyone 👋,&lt;/p&gt;

&lt;p&gt;I want to start by saying something that I know is going to make a certain type of person deeply uncomfortable, and I want to say it before the disclaimers, before the caveats, before the politely worded softening that usually surrounds this kind of statement. Here it is: I am sorry, but no. Neural networks are not capable of real, genuine, fully autonomous intelligence, and I need you to sit with that sentence for a moment before you start typing your rebuttal. I said genuine intelligence. Not artificial intelligence, not useful intelligence, not impressive intelligence. Genuine. That word is doing enormous work in that sentence, and I chose it with the same care I choose every other word I write. In my previous post &lt;a href="https://dev.to/wiseai/genuine-intelligence-will-never-in-trillion-years-emerge-from-neural-networks-1250"&gt;Genuine Intelligence will never in trillion years emerge from neural networks&lt;/a&gt;, I laid out the architectural argument from first principles. In &lt;a href="https://dev.to/wiseai/all-you-have-access-to-is-knowledge-and-tools-never-intelligence-5792"&gt;All You Have Access To Is Knowledge and Tools; Never Intelligence!&lt;/a&gt;, I showed that the entire intelligence narrative built around current AI systems is a category error dressed up in venture capital language. In &lt;a href="https://dev.to/wiseai/knowledge-and-intelligence-are-mutually-exclusive-kd4"&gt;Knowledge and Intelligence ARE Mutually Exclusive&lt;/a&gt;, I pushed that argument further. In this post I am going to go one more step, because something has shifted in the public conversation recently that requires a direct and unapologetic response, and I am the person who is apparently going to give it.&lt;/p&gt;

&lt;p&gt;The shift I am talking about is the following. A few months ago, the AI discourse was dominated by claims about language model reasoning. Before that it was claims about emergent capabilities. Before that it was claims about few-shot generalization. Each cycle, a new capability gets announced with increasing breathlessness, a new wave of LinkedIn posts declares that the singularity is here, and then 6 months later the researchers publish the papers showing what was actually happening under the hood, and it was pattern matching again. This cycle has been running for years. What is different now is that the current claims have escalated to the level of full autonomy. The claim is no longer that models can reason; the claim is that models are fully autonomous agents that can conduct scientific research, develop software, run business operations, and govern themselves without meaningful human oversight. And I need to explain, carefully and without being polite about it, why that claim is not just premature but structurally impossible given what neural networks actually are. Not impossible because the technology needs more time. Impossible because the mechanism is wrong. The same way a bicycle is structurally impossible to fly regardless of how technically refined it becomes, because the mechanism of a bicycle is not the mechanism of flight.&lt;/p&gt;

&lt;p&gt;I also want to say something before we go further about the phrase genuine autonomy, because I am using it in a specific and demanding sense and I want to be honest about what that sense is. Genuine autonomy means the capacity to set one's own goals, to evaluate the quality of one's own reasoning, to identify when one's own knowledge is insufficient, to decide what new knowledge to seek and how to seek it, to operate across novel domains that were not anticipated during design, and to do all of this without requiring a human at the end of the decision chain to validate, redirect, or supervise the process. That is the bar. It is a high bar. It is also the bar that every serious definition of autonomous agency sets, and it is the bar that current AI systems, regardless of wrapper, do not reach and cannot reach with the current architecture. I am going to spend the rest of this post explaining why with some humor because otherwise I would lose my mind, and with the same directness that I used in every post before this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, What Do You Mean By Genuine Intelligence vs Genuine Artificial Intelligence?
&lt;/h2&gt;

&lt;p&gt;I know the first objection coming, and I want to cut it off before it finishes forming. You are about to tell me that I am splitting linguistic hairs. You are about to say that the distinction between genuine intelligence and genuine artificial intelligence is just a semantic game, a rhetorical move that lets me redefine my terms whenever the AI does something impressive. I want to tell you no, and I want to tell you why. The distinction is not about semantics. It is about mechanism, and mechanism is the thing that determines what a system can and cannot do regardless of how impressive it looks from the outside. Genuine artificial intelligence, in the sense the term has been used since the 1950s, means systems that can mimic intelligent behavior. Artificial is the key word. The intelligence is a mimicry, an artifact, something made to resemble intelligence rather than something that is intelligence. We have had genuine artificial intelligence since GPT-1. The models predict plausible, contextually appropriate text. That is a form of artificial intelligence. It is impressive, it is useful, and nobody should pretend otherwise.&lt;/p&gt;

&lt;p&gt;Genuine intelligence, without the artificial qualifier, means something categorically different. It means the capacity to understand the world as it is rather than as it was described in the training data. It means the capacity to form new concepts from first principles rather than recombining concepts that were absorbed during training. It means the capacity to be wrong in a productive way, to notice the wrongness, to investigate it, to generate a hypothesis about why, to test that hypothesis against reality, and to update. It means the capacity to function in genuinely novel domains with no prior training context for that domain. A 12 year-old human child has genuine intelligence in this sense. The child can walk into an unfamiliar situation, form a model of what is happening, make predictions, get corrected by reality, and update their model. They do not need a training set for every new situation. They need the general capacity for model formation and causal reasoning, which develops through embodied experience in the physical world and which no transformer architecture produces through text prediction. The difference between these two kinds of intelligence is not a matter of degree. It is a matter of kind, and collapsing that distinction is how we end up with billion-dollar systems that confidently hallucinate medical diagnoses.&lt;/p&gt;

&lt;p&gt;I also want to address the specific version of the objection that says intelligence is a spectrum and the models are somewhere on it. This objection sounds measured and scientifically responsible, but it contains a hidden assumption that I reject, which is that the mechanisms of human intelligence and the mechanisms of neural network prediction are the same mechanism operating at different intensities. They are not. They are different mechanisms. A thermometer measures temperature in a way that is mechanistically completely different from how your body feels temperature. A photograph of a landscape is mechanistically completely different from a painting of the same landscape. Both the thermometer and your skin produce a response that covaries with temperature, but one is an engineered measurement and the other is a felt experience rooted in biology, and they are not on the same spectrum. Similarly, a language model produces outputs that covary with intelligent human outputs because it was trained to do so, but the process producing those outputs is mechanistically different from the process producing human intelligence, and being on a similar output spectrum does not make them the same kind of thing (1). The history of AI is full of systems that produced outputs indistinguishable from intelligent behavior on narrow tasks and then failed completely when the task changed even slightly. That failure is the signature of a mechanism mismatch, not a capability gap that will close with scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffzste65nx99bg7ovhgxv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffzste65nx99bg7ovhgxv.gif" alt="Explaining the difference between genuine and artificial intelligence to a tech bro" width="260" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The practical dimension of this distinction matters enormously and is not being discussed honestly in the public conversation. When companies deploy systems as autonomous agents and claim those systems are genuinely intelligent, they are making an implicit promise about the range of conditions under which those systems will perform reliably. Genuine intelligence implies robustness across novel conditions. Artificial intelligence implies reliable performance within the training distribution. Those promises are completely different in scope, and the gap between them is where people get hurt. A system that is genuinely autonomous can be trusted to handle situations that were not anticipated during design. A system that mimics autonomy can only be trusted to handle situations that are close to what it was trained on, which is a critically different trust relationship, and conflating them is how we end up with autonomous vehicles that fail in light rain, autonomous medical advisory systems that fail with unusual patient presentations, and autonomous coding agents that confidently introduce security vulnerabilities that no human reviewer would miss. The linguistic distinction between genuine and artificial intelligence is not a game. It is the most practically important distinction in the entire field.&lt;/p&gt;

&lt;h2&gt;
  
  
  But OpenAI Just Solved Mathematics, So Checkmate?
&lt;/h2&gt;

&lt;p&gt;Deep breath. Deep breath. Okay. Let me say this as kindly as I can manage, which is not very kindly. I already wrote about this general category of result in multiple previous posts and predicted it would happen, which means the result was not surprising to me, and I want to explain exactly why it should not be surprising to anyone who has been paying attention. A model trained on the entirety of human mathematical knowledge, which includes not just the correct theorems but the failed proofs, the partially solved problems, the heuristics, the analogies, the researcher notes, the textbook exercises, the competition problems, and the entire corpus of mathematical reasoning as expressed by humans over several centuries, that model generating solutions to problems that were previously unsolved is expected. I did not say it is unimpressive. I said it is expected. There is a difference, and the difference matters for what we conclude from it.&lt;/p&gt;

&lt;p&gt;The Navier-Stokes problem is a genuinely hard mathematical problem. Let nobody suggest I am dismissing its difficulty or its importance. But the way the model approaches a hard mathematical problem is not the way a mathematician approaches a hard mathematical problem. A mathematician builds a conceptual model of the problem space, identifies the structural feature that makes the problem hard, looks for analogies in other areas of mathematics that share that structural feature, formulates a hypothesis about what kind of argument strategy might work, explores that strategy, gets stuck, backtracks, reformulates, and eventually either succeeds or concludes that the approach was wrong. That process is generative intelligence operating on a causal model of the mathematical structure. What the model does is something statistically similar to pattern completion over a learned representation of mathematical text, and the fact that this can sometimes produce correct proofs for previously unsolved problems is remarkable but it is not evidence of genuine mathematical intelligence any more than a sufficiently detailed weather simulation is evidence that the simulation understands meteorology (2). The simulation produces correct predictions. It does not understand. The model produces correct proofs. It does not understand. These are not the same thing.&lt;/p&gt;

&lt;p&gt;I also want to say something about the specific framing of "OpenAI has solved mathematics" that appears in every breathless tech news headline when one of these results drops. Mathematics is not a set of problems to be solved. Mathematics is a living, generative discipline that creates new problems faster than it solves old ones, because in mathematics the solution to a problem almost always reveals new structure that opens 10 harder problems. The Mossad agents who normally help me with my architectural decisions apparently also help me with my epistemology, and they would point out that the interesting question is not whether the model can solve the existing unsolved problems but whether the model can formulate new problems that reveal new mathematical structure. Chollet argued in his landmark paper on measuring intelligence that skill acquired through training is fundamentally different from the fluid intelligence required to form entirely new problems, and that metrics which reward skill without measuring generalization ability give a systematically misleading picture of what a system can do (3). Ramanujan did not solve existing problems. He discovered entire new areas of mathematical structure that nobody had imagined. A language model trained on Ramanujan's work can reproduce patterns from his work. It cannot be Ramanujan.&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%2F14hqm4zw37h07pzgilin.jpeg" 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%2F14hqm4zw37h07pzgilin.jpeg" alt="Bro be tryna explain to the press that solving an existing problem is not the same as discovering a new field of mathematics" width="667" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pollution dimension of this situation also deserves explicit attention, because it is already happening and its consequences are already visible. As AI companies race to demonstrate mathematical or scientific capability, they are flooding academic preprint servers and research journals with AI-generated content at a rate that exceeds the human capacity for review and evaluation. The result is not an acceleration of scientific knowledge. The result is an acceleration of scientific content, which is a different and far more dangerous thing. Scientific content without the verification, the debate, the failed replication attempts, the collegial argument that slowly separates the genuine advance from the plausible-sounding error, that content is not science. It is noise that looks like science, and it degrades the ability of the research community to identify and build on genuine advances. I wrote in &lt;a href="https://dev.to/wiseai/llms-destroyed-the-internet-lmms-will-make-it-alive-1fbk"&gt;LLMs destroyed the Internet. LMMs will make it alive&lt;/a&gt; about how automated content generation destroys the epistemic value of the information environment. The same dynamic is now operating in the scientific literature, and the long-term cost is the trustworthiness of science itself. Nobody is excited. Nobody is shocked. And nobody should be, because this was predictable.&lt;/p&gt;

&lt;p&gt;I want to also directly address the human dimension of this, because I think it gets lost in the excitement over capability demonstrations. We human beings value effort not as a quirk of our psychology but because effort is the mechanism by which understanding is produced. The struggle to solve a hard problem, the years of failed attempts, the moments of insight that feel like gifts because they follow months of fruitless work, those are not inefficiencies to be optimized away. They are the process by which a human mind builds a deep causal model of a problem domain. When a system produces a solution without that struggle, the solution may be correct but it is also orphaned. It has no parent understanding. Nobody who holds that solution knows why it works in a deep enough sense to know where to go next. This is the reason that human mathematicians are, almost universally, not excited about AI-generated proofs. The proof is not the point. The understanding that the proof reveals is the point. A proof you did not struggle to find is a solution to a crossword puzzle completed by someone else. You have the answer. You do not have the understanding. And in mathematics, as in everything that actually matters, the understanding is the whole game.&lt;/p&gt;

&lt;h2&gt;
  
  
  But GPT-N Omega Pro Max++ Vibe-Coded This Entire Game Fully Autonomously?
&lt;/h2&gt;

&lt;p&gt;Here we go. Let me compose myself. Okay. I am composed. This argument comes up constantly now, and it follows the same template every time. An AI model, usually labeled with some impressive name involving a high number or a Greek letter, produces a functional artifact, usually a game, a website, or a piece of software, without explicit human instruction at the code level, and the result is presented as evidence of autonomous creativity and genuine intelligence. I need to take this apart, carefully and without losing my temper, because the argument is seductive and the counterargument requires more than a sentence to deliver properly. So let us be thorough about it.&lt;/p&gt;

&lt;p&gt;The first thing to understand about a model generating a functional game autonomously is what the word generating means in this context. The model does not create the game the way a human game developer creates a game. A human game developer starts with a vision, an aesthetic, a set of mechanics, a world, a set of rules that interact in interesting ways, and then implements all of that through a sequence of design and engineering decisions that each encode an aspect of the original vision. The interesting part is not the code. The interesting part is the creative vision that the code expresses. A language model generating a game produces code that is a collage of patterns from similar games in its training data, recombined in ways that happen to produce a functional result. The result may run correctly. It does not express a creative vision, because the model has no communicative intent, no aesthetic intention, no sense of what would be interesting or meaningful to a player. Bender et al. argued precisely this in their foundational critique of large language models: that these systems are stochastic parrots producing form without meaning, statistical mirrors of human text that carry none of the communicative intent that makes human language meaningful (4). It has learned what game code looks like, and it produces something that fits that learned distribution.&lt;/p&gt;

&lt;p&gt;The second thing to understand is that nobody wants to play the game. And this is not a small point. This is the entire point. A game's value to a player is not its technical correctness. A game's value is its soul, its lore, its narrative, its sense of humor, its respect for the player's time and intelligence, and above all its feeling of having been made by someone who cared about the experience of playing it. These are properties that I can detect immediately when I pick up a game, and so can you, even if you cannot articulate them precisely. When someone tells you that an LLM generated this entire game, something in you deflates, and that deflation is not irrational. It is a recognition that the thing is a hollow artifact. It runs, but nobody meant it. And meaning is not an optional luxury feature of creative work. Meaning is the entire reason creative work has value to the people who experience it. A game without meaning is just a physics engine with textures. You would get more out of asking the LLM to live-stream a playthrough of the game for you on the fly, which the LLM can do, and which would be more interesting to watch than playing a game that nobody genuinely imagined.&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%2Fgs8bjwzrzli5ha4l40gh.jpeg" 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%2Fgs8bjwzrzli5ha4l40gh.jpeg" alt="My Genuine reaction after downloading a fully AI-generated indie game." width="515" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The third thing to understand is the structural incompleteness of what gets described as fully autonomous generation. What the model actually did in every documented case of this type, when you look at the methodology rather than the marketing, is generate a frontend scaffold for a simple game loop, using patterns from similar open-source games in its training data. The complete experience of a game in the real world involves enormously more infrastructure than a scaffold. It involves backend services, matchmaking systems, chat infrastructure, anti-cheat systems, persistent player state, telemetry, analytics, abuse reporting, content moderation, accessibility features, localization, monetization systems, third-party service integrations, compliance with platform policies, and decades of iterative refinement based on player feedback. None of that exists in the autonomously generated output. What exists is a proof of concept that demonstrates the model can produce code that resembles the code of games it was trained on. Calling that full autonomous game development is like calling a photograph of a house the house. The photograph is an artifact that references the structure. The model output is an artifact that references the functionality. Neither of them are the thing itself.&lt;/p&gt;

&lt;p&gt;I also want to say something about the direction this argument is going, because I see it more and more: the claim that because the model can produce the surface form of creative work, the model is producing creative work, that because it can generate code that compiles, it is doing software engineering, that because it can write a sentence that is grammatically complex, it is engaging in literary expression. This is the philosopher's zombie problem applied to AI, and I want to name it clearly. A philosophical zombie, in thought experiment form, is an entity that behaves exactly like a conscious being in every observable respect but has no inner experience of that behavior. The behavior is there. The inner life is not. Current AI systems are philosophical zombies of intelligence. They produce the behavioral outputs associated with intelligence. The inner process producing those outputs is pattern completion over a learned statistical distribution, not reasoning, not understanding, not intention, not creativity. And a zombie playing chess is not a chess player. It is a zombie that makes moves. The distinction matters for what you trust the zombie to do next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What LLMs Are Actually Doing, and Why It Is Just The Tip of The Iceberg
&lt;/h2&gt;

&lt;p&gt;I want to be fair here, because I have been consistently fair in every post I have written, even when the thing I am being fair about is something that is actively used to argue against positions I hold. LLMs are powerful. They are more powerful than most people thought possible five years ago. They are useful, they are economically valuable, and the scale of what they can do within their training distribution is genuinely impressive. I wrote all of that in &lt;a href="https://dev.to/wiseai/llms-are-usefull-lmms-will-break-reality-8an"&gt;LLMs are Usefull. LMMs will Break Reality&lt;/a&gt;, and I stand by every word of it. But power within a training distribution is not the same as autonomy, and the gap between what LLMs can do and what production systems require is not a gap that can be bridged by wrapping the model in a better API.&lt;/p&gt;

&lt;p&gt;Think of a language model as a very sophisticated for-loop with memory. At each step, the loop looks at the current context, applies a search over the learned representation space, samples from the resulting distribution using some randomness to prevent deterministic collapse, and appends the result to the context before running the next iteration. That is a real and powerful computation. It is also a computation that is entirely reactive. It does not initiate. It does not plan beyond the immediate token horizon. It does not build a model of what it is trying to accomplish and monitor the gap between that model and the current state. It responds to input with statistically appropriate output. This is enormously useful for code completion, for document summarization, for information synthesis, for translation. It is not autonomous operation. Shanahan, in his careful philosophical treatment of what it means to talk about large language models honestly, argues that the anthropomorphism enabled by LLMs' fluency in human language makes us systematically vulnerable to describing them in terms that do not match their actual mechanism, and that repeated stepping back to ask what the system actually does will almost always reveal a reactive prediction engine rather than a reasoning actor (5).&lt;/p&gt;

&lt;p&gt;The production software systems that people actually run in the real world are not merely frontend scaffolds. They are layered stacks of interacting subsystems, each with its own failure modes, its own performance characteristics, its own operational requirements, and its own behavioral contracts with the other subsystems. A game on a real production platform has a game server cluster, a matchmaking service, a leaderboard service, a player identity and authentication service, a database cluster with replicas and backup procedures, a CDN for asset delivery, a monitoring and alerting stack, a deployment pipeline, a rollback procedure, a DDoS mitigation layer, and usually somewhere between three and five third-party service integrations that each have their own documentation, API limits, and failure behaviors. The model that generated the game frontend has no knowledge of any of this beyond the surface patterns it absorbed from documentation text in its training data. Building production systems is an exercise in understanding the mechanisms of failure across a complex interacting set of subsystems, and understanding failure mechanisms requires causal models that no language model has (6).&lt;/p&gt;

&lt;p&gt;The voice chat room in an online game is not a text generation problem. The latency constraints, the packet loss handling, the codec selection, the server-side mixing, the abuse detection in audio streams, the GDPR compliance for voice data, the integration with the client application, the regional routing for low latency, none of these are problems that get solved by generating plausible-sounding text about how voice chat would look. They are engineering problems that require deep understanding of network protocols, audio signal processing, distributed systems, regulatory frameworks, and the specific constraints of the game's platform and user base. The autonomously generated game has none of that. It has a textbox. And a textbox is not a voice chat room, no matter how many parameters the model that generated it has. This is not a criticism of the model. It is a description of what the model is and is not, and what production software is and is not, and why those two things are not the same.&lt;/p&gt;

&lt;p&gt;I want to connect this to something I said in &lt;a href="https://dev.to/wiseai/all-you-have-access-to-is-knowledge-and-tools-never-intelligence-5792"&gt;All You Have Access To Is Knowledge and Tools; Never Intelligence!&lt;/a&gt; about the frame problem. The frame problem, in practical engineering terms, is the problem of knowing which things change when you take an action and which things do not. When you deploy a new version of a service, what changes is the behavior of that service. What must not change, if you want your system to continue working, is the behavioral contracts between that service and everything it interacts with. Managing those contracts, reasoning about what is downstream of what, identifying which changes are safe and which are breaking, that is the daily work of a software engineer operating in a production system. It requires a causal model of the system. It requires the capacity to simulate what will happen when a change propagates through a layered stack of interacting services. A language model can produce code that looks like service code. It cannot reason causally about what will happen when that code runs in the production system, because it does not have a causal model of the production system. It has text about systems that look similar. That is the tip of the iceberg. The iceberg is everything that the text does not capture, and in production engineering, the iceberg is where ninety percent of the work lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Autonomy Illusion: How Wrappers Become Worldviews
&lt;/h2&gt;

&lt;p&gt;One of the most sophisticated-sounding arguments for AI autonomy goes like this: yes, the model itself is just pattern completion, but wrap it in the right scaffolding, give it memory, give it tools, give it the ability to call itself recursively, and you get something that is functionally autonomous even if the underlying mechanism is not. I hear this argument a lot from people who are technically sophisticated, and I want to engage with it honestly because it deserves engagement rather than dismissal. The argument is not crazy. There are systems architectures where simple computational units combine into systems with properties that no individual unit has. Neurons are simple threshold devices. Brains compute extraordinarily complex things. So why can't a simple language model plus scaffolding produce genuine autonomy?&lt;/p&gt;

&lt;p&gt;The answer is that the brain analogy fails at the level of mechanism, and mechanism is the thing that matters. Neurons combined into brains produce intelligence because the combination instantiates specific computational structures, specifically causal inference over hierarchical generative models, that are capable of producing genuine reasoning, genuine model formation, and genuine updating in response to prediction error (7). The computation is grounded in physical reality through sensorimotor experience that provides labeled prediction errors across millions of daily interactions. The structural organization of the brain, the cortical hierarchy, the basal ganglia, the hippocampal memory systems, the thalamic gating, is specifically adapted over millions of years of evolution to produce the kind of learning and inference that counts as intelligence. Wrapping a language model in scaffolding and memory does not replicate any of this. It adds a context management layer on top of a reactive prediction system. The scaffolding does not change what happens inside the prediction step, and the inside is where the intelligence would have to live.&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%2Fe2las4tcsxyeaekjx8s9.jpeg" 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%2Fe2las4tcsxyeaekjx8s9.jpeg" alt="The AI agent architecture diagram looking incredibly impressive." width="622" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memory does not solve the problem. Memory gives the model access to more text context. But having access to more text does not produce causal reasoning from that text. It produces pattern completion over more text. A model with a million-token context window is not more intelligent than a model with a four-thousand-token context window. It has more information available for its pattern completion. That is a real and useful improvement. It is not a mechanism for producing genuine reasoning, because the mechanism producing the output at each step is still pattern completion, regardless of how much context is available to that step (8). A person who reads more books is not smarter than a person who reads fewer books in any direct proportional sense. A person who reads more books has more raw material for their intelligence to work with. The intelligence doing the working is not in the books. It is in the cognitive architecture that was shaped by evolution and development long before the first book was opened.&lt;/p&gt;

&lt;p&gt;Tool use does not solve the problem either, and I made this argument at length in &lt;a href="https://dev.to/wiseai/all-you-have-access-to-is-knowledge-and-tools-never-intelligence-5792"&gt;All You Have Access To Is Knowledge and Tools; Never Intelligence!&lt;/a&gt;. A language model that can call a calculator, a search engine, and a code interpreter is a language model plus three lookup operations. The intelligence required to know which tool to use in which situation, to interpret what the tool returns, to integrate the tool output with the rest of the reasoning context, that intelligence has to live somewhere. And in the agentic architecture, the place it is supposed to live is the language model. But the language model's behavior in that role is still pattern completion over training data about how agents use tools, not genuine reasoning about which tool is appropriate for the current problem. The result is that the tool-augmented agent fails in characteristic pattern-matching ways on novel tool usage situations, which is exactly what the research shows (9). You can add recursion too. The model can call itself repeatedly, reflecting on its own output, generating a chain of self-assessments. But each step in that chain is still a pattern completion step, and a chain of pattern completion steps is not reasoning any more than a chain of coin flips is a decision. The appearance of self-reflection does not instantiate self-reflection.&lt;/p&gt;

&lt;p&gt;Genuine autonomy requires something that none of these scaffolding additions provide, which is an internal model of the task that allows the system to distinguish between situations where the current approach is working and situations where the current approach is failing, and to adaptively switch strategies based on that distinction. That is meta-cognitive control, the ability to monitor the quality of one's own cognitive processes and to intervene when quality is insufficient. Research on human metacognition has established that this capacity develops through years of embodied feedback, through the experience of trying, failing, noticing the failure, trying differently, and building a model of one's own cognitive strengths and weaknesses in specific domains. Language models have a statistical approximation of metacognitive language, they can produce text that sounds like self-assessment. They do not have the underlying process, the monitored internal model that the self-assessment text is supposed to describe. The words are there. The referent is not. And an autonomous agent without genuine metacognitive control is not an autonomous agent. It is a system that will continue confidently in the wrong direction for as long as the statistical distribution of its training data supports doing so.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Research Nobody Wants to Read But Everybody Should
&lt;/h2&gt;

&lt;p&gt;I want to spend time in this section on the empirical evidence, because I believe strongly that the argument I am making is not just philosophically sound but empirically grounded in a body of research that is not making it into the popular conversation with the prominence it deserves. The popular conversation about AI capability is substantially driven by benchmark performance announcements, demo videos, and press releases. The empirical research literature on what AI systems cannot do is substantially less visible. That asymmetry is not neutral. It shapes what people believe about the current state and trajectory of AI, and beliefs shape decisions, and decisions about AI deployment have real consequences for real people.&lt;/p&gt;

&lt;p&gt;The research on AI agent reliability is the most directly relevant to the autonomy question, and the results are unambiguous. Kambhampati et al. demonstrated from first principles that auto-regressive LLMs cannot, by themselves, perform sound planning or self-verification, because the next-token prediction mechanism does not implement the look-ahead and backtracking required for global goal alignment (9). This theoretical argument is validated empirically in large-scale agent benchmarks: the WebArena evaluation placed state-of-the-art GPT-4-based agents on realistic long-horizon web tasks and measured a task success rate of only 14.41 percent against a human success rate of 78.24 percent, representing failure rates exceeding eighty-five percent on tasks that a capable human completes routinely (10). The failure modes are consistent and predictable: agents take locally plausible actions that compound into globally incorrect outcomes, and when they encounter situations that do not match their training distribution, they either fail to recognize the mismatch or continue confidently toward the wrong outcome. These are not random failures. They are the systematic signature of a system that lacks a global model of the task and is therefore unable to detect when the local action is inconsistent with the global goal. A genuinely autonomous system would detect this inconsistency and recover. A pattern-matching system cannot, because detecting the inconsistency requires comparing the current state against a model of the intended state, and that kind of model-based comparison is not what pattern completion produces.&lt;/p&gt;

&lt;p&gt;The research on distribution shift, which I discussed in &lt;a href="https://dev.to/wiseai/genuine-intelligence-will-never-in-trillion-years-emerge-from-neural-networks-1250"&gt;Genuine Intelligence will never in trillion years emerge from neural networks&lt;/a&gt;, has continued to accumulate in the same direction. Study after study finds that AI systems perform reliably within their training distribution and unreliably outside it, and the performance degradation is dramatic rather than gradual. Taori et al. systematically evaluated 204 ImageNet classification models across 213 different test conditions and found that robustness gains from synthetic perturbation training rarely transferred to natural distribution shifts, and that virtually no existing technique fully closes the performance gap between in-distribution and naturally shifted test sets (11). This is the canonical signature of a system that has learned to exploit statistical regularities in the training data rather than learning the underlying rule that generates the data, and it appears consistently across architectures, scales, and domains. It does not go away with more scale. It changes in its specific manifestations as the model becomes more capable within its distribution, but the structural incompatibility between pattern matching and genuine generalization remains. More impressive pattern matching is still pattern matching, and pattern matching does not become autonomy at any scale.&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%2Fxdulczjgyaueavzvultl.jpeg" 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%2Fxdulczjgyaueavzvultl.jpeg" alt="Research paper that proves LLMs are pattern matchers appearing in the preprint server." width="637" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The research on AI in high-stakes professional domains is perhaps the most concrete evidence of the autonomy gap, because these are exactly the domains where genuine autonomy would be most valuable and where its absence is most costly. Obermeyer et al. conducted a landmark analysis of a commercial health-management algorithm and found that it systematically underestimated the health needs of Black patients because it used healthcare cost as a proxy for health need, encoding the structural reality that Black patients had less access to care into a learned bias that treated them as healthier than equally sick White patients (12). The algorithm was not doing medicine. It was doing pattern matching over a dataset where the patterns encoded centuries of unequal access. A genuinely autonomous medical reasoner, one operating from a causal model of pathophysiology, would not confuse spending patterns with health status. A pattern-matching system cannot distinguish between them, because in its training data, they covary, and covariation is all it can learn. The bias shows up not as a subtle statistical artefact but as a systematic, measurable failure that affects real patients in real clinical settings, and it is invisible to the system producing it because the system has no model of the mechanism generating the pattern.&lt;/p&gt;

&lt;p&gt;The research on AI legal reasoning has found similar patterns. Dahl et al. conducted the first systematic profiling of legal hallucinations in large language models and found that legal hallucinations were alarmingly prevalent, occurring between 58 percent of the time with GPT-4 and 88 percent of the time with Llama 2 when models were asked specific, verifiable questions about federal court cases (13). The model that passes the bar examination has learned the statistical distribution of bar examination questions, which is a specific and relatively well-defined distribution that diligent pattern matching can handle. But when the same model is asked to retrieve or reason about actual legal specifics, specific case names, specific holdings, specific statutes in specific jurisdictions applied to specific novel fact patterns, it confabulates with high confidence, because the specific combination has no reliable match in the training distribution and the model has no actual model of legal structure to reason from. Dahl et al. also found that LLMs often cannot correct a user's incorrect legal assumptions, and frequently do not know when they are producing a hallucination, which is the overconfidence signature in its most dangerous possible form. This is happening in systems already deployed in real legal contexts, serving real clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Genuine Intelligence Requires Genuine Grounding, and That Grounding Cannot Be Simulated in Tokens
&lt;/h2&gt;

&lt;p&gt;There is a philosophical concept called grounding and it explains a great deal about why text-trained models cannot achieve genuine autonomy. Grounding refers to the connection between a symbol and the thing in the world that the symbol refers to. When I use the word hot, my use of that word is grounded in my experience of touching hot surfaces, of feeling the burns, the warmth, the danger signal, the automatic withdrawal reflex. That experience is what gives the word hot a meaning that goes beyond its statistical relationship with other words. A language model's use of the word hot is statistically associated with other words like fire, pain, temperature, summer, and coffee, and that statistical association allows it to produce contextually appropriate text involving the word hot. But the word is not grounded in any felt experience of heat. It is an ungrounded symbol, and ungrounded symbols cannot support genuine reasoning about the referents of those symbols in the way that grounded symbols can (14).&lt;/p&gt;

&lt;p&gt;The grounding problem is not merely philosophical. It has direct practical consequences that show up in specific failure modes. A model with ungrounded symbols cannot reason about physical interactions in novel situations because its knowledge of physical interactions is stored as statistical associations between words that describe physical interactions, not as a model of the physics itself. Ask the model to predict what will happen when you drop a cube of ice into a glass of warm water, and it will produce the correct answer because that scenario is well-represented in its training data. Ask it to predict what will happen when you drop a specific non-standard material with specific non-standard thermodynamic properties into a specific non-standard fluid under non-standard pressure, and it will confabulate, because the specific combination has no statistical precursor in the training data and the model has no actual physical simulation to fall back on. A genuinely intelligent system would use its physical model, its understanding of thermodynamics, to compute the answer for any combination of materials and conditions. The model uses its training data, which means it only knows what it has been told about specific scenarios. And there are infinitely many specific scenarios that nobody has written text about.&lt;/p&gt;

&lt;p&gt;The solution to the grounding problem is not more text. More text does not ground symbols in physical reality. More text gives you more ungrounded symbols with richer statistical relationships to each other. A model trained on every physics textbook ever written has abundant statistical associations between physics words. It does not have a single simulation of a physical process grounded in the actual dynamics of the physical world. This is why I have argued across multiple posts for the importance of mathematical models and physics simulations as the alternative architecture. &lt;a href="https://dev.to/wiseai/mathematical-equations-are-multimodal-by-default-53fk"&gt;Mathematical Equations are Multimodal by default&lt;/a&gt; describes why equations are more honest representations of physical reality than text, because equations encode the mechanism rather than a description of the mechanism, and mechanisms are what ground the predictions in reality. A model built around equation discovery and physical simulation has symbols that are grounded in the dynamics of physical reality. A language model has symbols grounded only in other text. The first kind of grounding supports genuine reasoning about novel physical situations. The second kind supports sophisticated text generation about familiar textual patterns. Those are not the same capability.&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%2Fr9xmb4mwtglwuzmiaytv.jpeg" 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%2Fr9xmb4mwtglwuzmiaytv.jpeg" alt="A philosophical zombie" width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Embodied cognition research has established over the past three decades that human intelligence is not separable from the body that hosts it and the physical world that the body interacts with (16). When you understand what it means to grasp something, that understanding is rooted in the sensorimotor experience of grasping, the feel of fingers closing, the resistance of the object, the proprioceptive sense of hand position and grip strength. Your understanding of the abstract concept grasping a concept is a metaphorical extension of that embodied experience, and research shows that even processing abstract language activates sensorimotor neural systems involved in the corresponding physical actions. Intelligence is not a disembodied computation over abstract symbols. It is a computation deeply intertwined with a physical body that experiences the world and updates its models on the basis of that experience. Language models, by design, have no body, no sensorimotor experience, no felt consequences for wrong predictions, and no physical world to update against. They have text. Text is a description of embodied experience. A description of embodied experience is not the same as embodied experience, and intelligence built on descriptions cannot do what intelligence built on experience can do.&lt;/p&gt;

&lt;p&gt;I want to close this section by saying something about what genuine grounding would require that I think is underappreciated. Genuine grounding requires not just sensory data but the feedback loop between predictions and their consequences. It requires a system that has made predictions about the physical world and had those predictions either confirmed or disconfirmed by events in that physical world, and that has updated its internal model on the basis of that feedback. This is the reinforcement learning setup in its genuine sense, not the RLHF approximation that is used to fine-tune language models, but actual reinforcement learning where the signal comes from the physical world. Reinforcement learning in that genuine sense can produce grounded representations of the world, as demonstrated by robotics systems and simulation-trained physical agents. But those systems are not language models. They are a different architecture solving a fundamentally different problem. And the intelligence produced by genuine reinforcement learning against physical reality does not transfer from the language model paradigm regardless of how large the language model becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  We Do Not Even Know What We Do Not Know, and That Is the Real Problem
&lt;/h2&gt;

&lt;p&gt;One of the most dangerous properties of current AI systems in deployment is the combination of high capability within the training distribution and high confidence everywhere. The system does not degrade gracefully as it approaches the edge of its competence. It falls off a cliff while still sounding absolutely certain. This is the property that I find most troubling about the current deployment environment, more troubling than any specific failure mode, because it makes the failures unpredictable and therefore unmanageable. If a system degraded gracefully and signaled increasing uncertainty as it approached the edge of its competence, you could deploy it with appropriate monitoring and respond to the signals before the failures had consequences. But a system that fails while sounding confident fails silently, from the user's perspective, until the failure has already had consequences.&lt;/p&gt;

&lt;p&gt;Calibrated uncertainty, the property of knowing what you do not know, is a defining feature of genuine intelligence and a property that neural networks systematically lack in their base form. Guo et al. demonstrated in a foundational study of neural network calibration that modern deep neural networks are poorly calibrated compared to their predecessors, that they are systematically overconfident, and that this overconfidence grows with model depth, width, and the use of batch normalization, meaning that the architectural choices that make neural networks more accurate also make them more overconfident in their wrong answers (15). A model that has seen many confident-sounding statements in its training data will produce confident-sounding statements in contexts that resemble its training data, regardless of whether that confidence is warranted in the specific case. This is not a calibration bug that can be patched. It is a structural consequence of the training objective, which rewards producing confident predictions on training examples and has no direct mechanism to penalize overconfidence in the specific situations where the model's knowledge is weakest.&lt;/p&gt;

&lt;p&gt;The absence of genuine metacognitive monitoring is the root cause. A genuinely intelligent system would monitor the quality of its own reasoning, flag when it was operating in unfamiliar territory, and scale its expressed confidence to match its actual epistemic state. This kind of metacognitive monitoring is what humans call knowing what you know and knowing what you don't know, and while humans are imperfect at it, the basic capacity exists and can be trained and improved. In neural networks, the absence is architectural. The model produces its outputs through a single forward pass, without any separate process that monitors the quality of the reasoning or evaluates the confidence of the output against the strength of the evidence. Techniques like sampling-based uncertainty estimation give a proxy for disagreement between model samples, but that proxy is not the same as genuine metacognitive monitoring, and it does not prevent the confident production of confident-sounding wrong answers. The model does not know what it does not know because it does not have a model of what it knows. It has weights. Weights do not know things. They encode statistical associations, and statistical associations do not have an epistemic status that the model can introspect and evaluate.&lt;/p&gt;

&lt;p&gt;For a genuinely autonomous system, calibrated uncertainty is not optional. It is the mechanism by which an autonomous agent decides when to act on its own judgment and when to seek additional information, defer to a human, or flag a decision as requiring review. Without this mechanism, an autonomous agent will make high-stakes decisions in low-competence situations with the same apparent confidence as low-stakes decisions in high-competence situations, and the consequences of that cannot be managed at the deployment layer. You cannot fix a systematic overconfidence problem with monitoring alone, because the monitoring has to use the same system's outputs to assess the same system's confidence, and the system is wrong about its own confidence. This is the autonomy gap in its most concrete operational form. An autonomous vehicle that does not know where its competence ends is not safer than a human driver who does know where their competence ends. It is dramatically less safe. And scaling the model does not change the fundamental absence of the metacognitive architecture that would make it possible for the model to know what it does not know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Would Genuine Autonomous Intelligence Actually Require?
&lt;/h2&gt;

&lt;p&gt;I want to be honest and constructive here because I have been making a primarily negative argument for most of this post and I genuinely believe in the possibility of building genuinely autonomous intelligent systems. I do not believe current neural networks can get us there. I believe the alternative direction exists and is the right one, and I want to describe it clearly. If you have read my previous posts, you have seen pieces of this argument scattered across multiple places. Here I want to assemble those pieces into a description of what the right architecture would need to look like.&lt;/p&gt;

&lt;p&gt;First, it would need causal modeling rather than statistical association. The difference is not subtle. A causal model of a domain represents the mechanisms that generate the observations, not just the statistical relationships between observations. A causal model of a medical domain would represent the biological mechanisms by which diseases produce symptoms, not the statistical correlation between symptoms and diagnoses in a training dataset. Causal models support genuine generalization because they generalize at the level of mechanism, which is domain-invariant, rather than at the level of surface patterns, which are training-distribution-specific. Judea Pearl's work on causal inference and the do-calculus provides the mathematical foundation for this, and the field of causal machine learning, while early stage, is producing real results (17). This is the right direction. It is also harder, slower, and less impressive in demos than scaling language models, which is why it is underfunded and understaffed relative to its importance.&lt;/p&gt;

&lt;p&gt;Second, it would need symbolic reasoning over learned representations, not just learned representations by themselves. Symbolic reasoning is what provides the truth-preserving inference rules that allow a genuine reasoner to derive new knowledge from known knowledge in ways that are reliable rather than statistically likely. The neurosymbolic research program, which I described in &lt;a href="https://dev.to/wiseai/genuine-intelligence-will-never-in-trillion-years-emerge-from-neural-networks-1250"&gt;Genuine Intelligence will never in trillion years emerge from neural networks&lt;/a&gt;, is the most promising approach here. It attempts to combine the representation learning strengths of neural networks with the structured inference strengths of symbolic systems. The engineering challenges are real but the theoretical case is solid. A system that can learn good representations from data and reason over those representations using principled inference rules would have systematic compositionality, would support genuine logical reasoning, and would avoid the surface-pattern dependence that characterizes pure neural approaches.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fykwsn5sh7yxwfdt9izx7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fykwsn5sh7yxwfdt9izx7.gif" alt="Me tryna to explain to the average AI journalist" width="480" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third, it would need physical grounding through interaction with the real world rather than text descriptions of the real world. This means some form of sensorimotor experience, either through robotics, through physics simulation with real physical fidelity, or through other forms of direct interaction with physical processes that produce genuine prediction errors when the system's model is wrong. The &lt;a href="https://github.com/wiseaidotdev/lmm" rel="noopener noreferrer"&gt;lmm project&lt;/a&gt; I have been building is an attempt to implement a piece of this, with symbolic regression for discovering physical equations from data rather than ingesting descriptions of physical equations from text. An LMM architecture that learns physical laws from measurements of physical processes has symbols grounded in physical reality in a way that a language model trained on text descriptions of physical laws does not. The grounding is genuine because the equations have been validated against real physical data, not because someone wrote down that the equations are valid.&lt;/p&gt;

&lt;p&gt;Fourth, it would need genuine metacognitive architecture, a separate process that monitors the quality of the primary reasoning process and has the authority to intervene, redirect, or flag uncertainty when warranted. This is not the same as adding a reflection step to the language model output. A reflection step is still a language model output, a pattern completion over descriptions of what good reflection looks like. A genuine metacognitive architecture is a separate computational process with a different objective from the primary reasoning process, specifically the objective of evaluating whether the primary reasoning is working and the objective of identifying when it is not. The computational structure for this exists in various proposals in the cognitive science and AI literature, and while no current system implements it in a satisfying way, it is a tractable engineering problem rather than an impossible one. The impossibility is not in building genuine metacognitive architecture. The impossibility is in producing genuine metacognition from a single-objective next-token prediction training process. You need to build the metacognitive capacity explicitly. It does not emerge from scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Do We Go From Here, And What Honest Progress Looks Like
&lt;/h2&gt;

&lt;p&gt;I want to close this post the way I have closed every post before it, which is by saying something honest rather than something comfortable. The honest state of affairs is this: neural networks are extraordinarily powerful tools that operate within their training distributions with impressive and genuinely useful capability. They are not genuinely autonomous agents, they are not genuinely intelligent, and they will not become either of these things through further scaling of the same architecture. The gap between what they are and what genuine autonomous intelligence requires is architectural, not quantitative, and architectural gaps require different architectures, not more of the same architecture. This is not pessimism about AI. This is clarity about what the current tools are and a call for honesty about the gap between them and what we are claiming to build.&lt;/p&gt;

&lt;p&gt;The progress that would actually matter, the progress toward systems that can reason causally, that have grounded representations, that can generalize systematically, that know what they do not know, is happening in smaller research communities with less funding and less visibility than the communities building larger and larger language models. Causal machine learning, neurosymbolic AI, physics-informed learning, symbolic regression, embodied AI, all of these research directions are producing results that are more relevant to genuine autonomous intelligence than anything coming out of the scaling race, and they are producing those results with a fraction of the compute and a fraction of the investment. The academic incentive structure, the funding structure, and the media attention structure are all pointing in the wrong direction. The right direction is harder, slower, and does not produce demos that trend on social media. But it is the direction that leads somewhere real.&lt;/p&gt;

&lt;p&gt;For those of you who build things, which is most of the people I know and most of the people who read this blog, the honest implication of this argument is that you should use current AI tools for what they are good at, which is significant, and build your systems with appropriate understanding of where those tools fail. Do not build systems that depend on AI judgment in situations that fall outside the training distribution unless you have robust monitoring and human oversight for exactly those situations. Do not tell your users that your system is autonomous when it is a language model in a scheduling for-loop. Do not cite benchmark performance as evidence of real-world capability in novel domains. These are not technical requirements. They are honesty requirements. And honesty about what our tools can and cannot do is the minimum ethical obligation of anyone who builds and deploys systems that affect other people's lives.&lt;/p&gt;

&lt;p&gt;The future I want to build toward, and the one I am working on in my small way with the &lt;a href="https://github.com/wiseaidotdev/lmm" rel="noopener noreferrer"&gt;lmm project&lt;/a&gt;, is a future where artificial systems earn the word autonomous through demonstrated behavior in situations that were not anticipated during design. Not through impressive demo performance on curated benchmarks. Not through confident-sounding answers to questions that happen to be in-distribution. Through genuine generalization to genuine novelty, through honest uncertainty when facing unfamiliar territory, through the capacity to form new understanding rather than retrieve old patterns. That future is technically achievable. It requires different architecture, different training objectives, different evaluation criteria, and different honesty from everyone involved in building and deploying these systems. It also requires that we stop congratulating ourselves for the current tools as though they are already there, because they are not, and pretending otherwise is how we make the journey longer, not shorter.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;span id="ref-1"&gt;&lt;/span&gt;&lt;strong&gt;1.&lt;/strong&gt; Searle, J. R., &lt;em&gt;Minds, Brains, and Programs&lt;/em&gt;, &lt;a href="https://www.cambridge.org/core/journals/behavioral-and-brain-sciences/article/abs/minds-brains-and-programs/DC644B47A4299C637C89772FACC2706A" rel="noopener noreferrer"&gt;Behavioral and Brain Sciences, 1980&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-2"&gt;&lt;/span&gt;&lt;strong&gt;2.&lt;/strong&gt; Marcus, G. &amp;amp; Davis, E., &lt;em&gt;Rebooting AI: Building Artificial Intelligence We Can Trust&lt;/em&gt;, &lt;a href="https://www.penguinrandomhouse.com/books/603982/rebooting-ai-by-gary-marcus-and-ernest-davis" rel="noopener noreferrer"&gt;Pantheon Books, 2019&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-3"&gt;&lt;/span&gt;&lt;strong&gt;3.&lt;/strong&gt; Chollet, F., &lt;em&gt;On the Measure of Intelligence&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/1911.01547" rel="noopener noreferrer"&gt;arXiv:1911.01547&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-4"&gt;&lt;/span&gt;&lt;strong&gt;4.&lt;/strong&gt; Bender, E. M., Gebru, T., McMillan-Major, A. &amp;amp; Shmitchell, S., &lt;em&gt;On the Dangers of Stochastic Parrots: Can Language Models Be Too Big?&lt;/em&gt;, &lt;a href="https://archive.org/details/stochastic-parrots-3442188.3445922" rel="noopener noreferrer"&gt;ACM FAccT 2021&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-5"&gt;&lt;/span&gt;&lt;strong&gt;5.&lt;/strong&gt; Shanahan, M., &lt;em&gt;Talking About Large Language Models&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2212.03551" rel="noopener noreferrer"&gt;arXiv:2212.03551&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-6"&gt;&lt;/span&gt;&lt;strong&gt;6.&lt;/strong&gt; Bommasani, R. et al., &lt;em&gt;On the Opportunities and Risks of Foundation Models&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2108.07258" rel="noopener noreferrer"&gt;arXiv:2108.07258&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-7"&gt;&lt;/span&gt;&lt;strong&gt;7.&lt;/strong&gt; Friston, K., &lt;em&gt;The free-energy principle: a unified brain theory?&lt;/em&gt;, &lt;a href="https://www.nature.com/articles/nrn2787" rel="noopener noreferrer"&gt;Nature Reviews Neuroscience, 2010&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-8"&gt;&lt;/span&gt;&lt;strong&gt;8.&lt;/strong&gt; Dziri, N. et al., &lt;em&gt;Faith and Fate: Limits of Transformers on Compositionality&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2305.18654" rel="noopener noreferrer"&gt;arXiv:2305.18654&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-9"&gt;&lt;/span&gt;&lt;strong&gt;9.&lt;/strong&gt; Kambhampati, S. et al., &lt;em&gt;LLMs Can't Plan, But Can Help Planning in LLM-Modulo Frameworks&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2402.01817" rel="noopener noreferrer"&gt;arXiv:2402.01817&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-10"&gt;&lt;/span&gt;&lt;strong&gt;10.&lt;/strong&gt; Zhou, S. et al., &lt;em&gt;WebArena: A Realistic Web Environment for Building Autonomous Agents&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2307.13854" rel="noopener noreferrer"&gt;arXiv:2307.13854&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-11"&gt;&lt;/span&gt;&lt;strong&gt;11.&lt;/strong&gt; Taori, R. et al., &lt;em&gt;Measuring Robustness to Natural Distribution Shifts in Image Classification&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2007.00644" rel="noopener noreferrer"&gt;arXiv:2007.00644&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-12"&gt;&lt;/span&gt;&lt;strong&gt;12.&lt;/strong&gt; Obermeyer, Z., Powers, B., Vogeli, C. &amp;amp; Mullainathan, S., &lt;em&gt;Dissecting racial bias in an algorithm used to manage the health of populations&lt;/em&gt;, &lt;a href="https://pubmed.ncbi.nlm.nih.gov/31649194/" rel="noopener noreferrer"&gt;Science, Vol. 366, 2019&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-13"&gt;&lt;/span&gt;&lt;strong&gt;13.&lt;/strong&gt; Dahl, M. et al., &lt;em&gt;Large Legal Fictions: Profiling Legal Hallucinations in Large Language Models&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2401.01301" rel="noopener noreferrer"&gt;arXiv:2401.01301&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-14"&gt;&lt;/span&gt;&lt;strong&gt;14.&lt;/strong&gt; Harnad, S., &lt;em&gt;The Symbol Grounding Problem&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/cs/9906002" rel="noopener noreferrer"&gt;Physica D: Nonlinear Phenomena, 1990&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-15"&gt;&lt;/span&gt;&lt;strong&gt;15.&lt;/strong&gt; Guo, C. et al., &lt;em&gt;On Calibration of Modern Neural Networks&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/1706.04599" rel="noopener noreferrer"&gt;ICML 2017&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-16"&gt;&lt;/span&gt;&lt;strong&gt;16.&lt;/strong&gt; Lakoff, G. &amp;amp; Johnson, M., &lt;em&gt;Philosophy in the Flesh: The Embodied Mind and Its Challenge to Western Thought&lt;/em&gt;, &lt;a href="https://openlibrary.org/works/OL1952995W/Philosophy_in_the_flesh" rel="noopener noreferrer"&gt;Basic Books, 1999&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span id="ref-17"&gt;&lt;/span&gt;&lt;strong&gt;17.&lt;/strong&gt; Pearl, J., &lt;em&gt;Causality: Models, Reasoning, and Inference&lt;/em&gt;, &lt;a href="https://www.cambridge.org/core/books/causality/B0046844FAE10CBF274D4ACBDAEB5F5B" rel="noopener noreferrer"&gt;Cambridge University Press, 2009&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>lmm</category>
      <category>discuss</category>
    </item>
    <item>
      <title>🔐 OTP RS: RFC-Compliant OTP Input Components for WASM Frameworks</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 04 Oct 2026 11:24:36 +0000</pubDate>
      <link>https://dev.to/wiseai/otp-rs-rfc-compliant-otp-input-components-for-wasm-frameworks-i45</link>
      <guid>https://dev.to/wiseai/otp-rs-rfc-compliant-otp-input-components-for-wasm-frameworks-i45</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Nǐ hǎo 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You've seen the textbox. You've typed the number. You've waited three seconds for the SMS that never came, checked your spam folder, clicked "Resend", typed the number again, and finally admitted to yourself that 2FA is simultaneously the most important and most annoying invention of the modern web.&lt;/p&gt;

&lt;p&gt;Today, we make it marginally less annoying, at least on the Rust side. We're shipping &lt;a href="https://github.com/opensass/otprs" rel="noopener noreferrer"&gt;&lt;strong&gt;OTP RS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What Even Is OTP RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OTP RS&lt;/strong&gt; is a composable, accessible, animated One-Time Password input component for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. It implements the full verifier flow: slot-by-slot input, keyboard navigation, active/filled/invalid/disabled states, animated caret blink, digit-entry pop animation, and &lt;a href="https://rfc-editor.org/info/rfc4226" rel="noopener noreferrer"&gt;RFC 4226 (HOTP)&lt;/a&gt; + &lt;a href="https://www.rfc-editor.org/info/rfc6238" rel="noopener noreferrer"&gt;RFC 6238 (TOTP)&lt;/a&gt; validation, all in Rust, all in WASM, all without touching a single line of JavaScript.&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%2Flu7g9tcbso2f22jgqfty.jpeg" 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%2Flu7g9tcbso2f22jgqfty.jpeg" alt="one does not simply implement OTP" width="651" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever tried to build a 6-box OTP input from scratch, you know the drill. It starts with "just six inputs". Two hours later you're debugging focus management, backspace propagation, keyboard event edge cases, browser autofill hijacking your state, and the invisible iOS number pad refusing to appear. That's the origin story of OTP RS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component Architecture
&lt;/h2&gt;

&lt;p&gt;OTP RS follows the same composable anatomy as every other component in the Open SASS Kit. You compose what you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Otp&lt;/code&gt;&lt;/strong&gt;: Root container. Owns the internal value state, focus coordination, and the RFC validation callbacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Group&lt;/code&gt;&lt;/strong&gt;: A visual cluster of slots (e.g., three digits, then a separator, then three more).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Slot&lt;/code&gt;&lt;/strong&gt;: Individual slot. Renders a visible character display on top of an invisible overlay &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Separator&lt;/code&gt;&lt;/strong&gt;: The little dash in between groups.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;otprs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Otp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Separator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Slot&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[function_component(VerificationInput)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;verification_input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Otp&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter your OTP"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Separator&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&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="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Otp&lt;/span&gt;&lt;span class="o"&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;That's it. Focus management, digit propagation, state aggregation, and ARIA attributes are all handled. You just compose slots.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Invisible Input Trick
&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%2Fsc52a6iybhcjqxplzogv.jpeg" 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%2Fsc52a6iybhcjqxplzogv.jpeg" alt="What if I told you ma boy" width="643" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the most important design decision in all of OTP RS: &lt;strong&gt;the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element that receives keyboard events is completely invisible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;Slot&lt;/code&gt; renders two layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An invisible &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; (via &lt;code&gt;input-rs&lt;/code&gt; with &lt;code&gt;otp_mode=true&lt;/code&gt;) that is &lt;code&gt;position: absolute; inset: 0; opacity: 0&lt;/code&gt;. It captures all keyboard focus and input events.&lt;/li&gt;
&lt;li&gt;A visible &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; that displays the digit character and the blinking caret.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This separates the &lt;strong&gt;input mechanics&lt;/strong&gt; from the &lt;strong&gt;visual presentation&lt;/strong&gt;, giving us full control over the slot's look without fighting browser defaults for &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; styling.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────┐
│  Slot wrapper       │  ← position: relative; border; background; animation
│  ┌───────────────┐  │
│  │ &amp;lt;input&amp;gt;       │  │  ← absolute; opacity:0; captures keyboard events
│  └───────────────┘  │
│  &amp;lt;span&amp;gt;3&amp;lt;/span&amp;gt;     │  ← visible character display
│  &amp;lt;span class=caret/&amp;gt;│  ← blinking caret (when active &amp;amp; empty)
└─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Invisible Input That Wasn't Actually Invisible
&lt;/h2&gt;

&lt;p&gt;Here's a fun bug that bit us early on, hard.&lt;/p&gt;

&lt;p&gt;The slot design described above only works if the CSS for the invisible input is applied as an &lt;strong&gt;inline &lt;code&gt;style&lt;/code&gt; attribute&lt;/strong&gt;, not as a CSS &lt;code&gt;class&lt;/code&gt; attribute. The component originally passed the overlay CSS string to &lt;code&gt;input_class&lt;/code&gt;, a prop that sets the HTML &lt;code&gt;class=""&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Browsers don't style elements based on CSS property strings stuck in the class attribute. They look up class names in stylesheets. So what we got instead of an invisible overlay was a white rectangle aggressively covering the entire OTP component, like a censored emoji on live TV.&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%2Fz92y6bfd9cchnv5tep4w.jpeg" 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%2Fz92y6bfd9cchnv5tep4w.jpeg" alt="that's not how this works meme" width="620" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fix was to add an &lt;code&gt;input_style: &amp;amp;'static str&lt;/code&gt; prop to &lt;code&gt;input-rs&lt;/code&gt; in all three framework implementations, and apply it as &lt;code&gt;style="{props.input_style}"&lt;/code&gt; on the bare otp_mode &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;. One line per framework. Six characters (&lt;code&gt;_style&lt;/code&gt; vs &lt;code&gt;_class&lt;/code&gt;). Three frameworks. Three PRs worth of suffering.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Compiler Is Your Enemy (And Also Your Best Friend)
&lt;/h2&gt;

&lt;p&gt;Let us count the ways Rust fought us this time.&lt;/p&gt;
&lt;h3&gt;
  
  
  Episode 1: Hook in a Macro
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;E0277&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Hook&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&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="n"&gt;IntoPropValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;...&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;satisfied&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We tried calling &lt;code&gt;use_state(...)&lt;/code&gt; inside an &lt;code&gt;html!&lt;/code&gt; macro attribute. Yew forbids calling hooks anywhere except directly inside function component bodies. The macro expands to a closure, and hook calls need to be at the top level. Extracting &lt;code&gt;use_state&lt;/code&gt; calls to &lt;code&gt;let&lt;/code&gt; bindings before &lt;code&gt;html!&lt;/code&gt; fixed it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Episode 2: &lt;code&gt;Box::leak&lt;/code&gt; and the &lt;code&gt;&amp;amp;'static str&lt;/code&gt; Obligation
&lt;/h3&gt;

&lt;p&gt;Dioxus and Leptos's &lt;code&gt;input-rs&lt;/code&gt; props require &lt;code&gt;&amp;amp;'static str&lt;/code&gt;. But our slot-specific strings like &lt;code&gt;"Digit 3"&lt;/code&gt; are computed at runtime. The only way to produce a &lt;code&gt;&amp;amp;'static str&lt;/code&gt; from a runtime &lt;code&gt;String&lt;/code&gt; without pulling in a string interner is to &lt;code&gt;Box::leak&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;leak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Digit {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into_boxed_str&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;Yes, this leaks memory on every slot render. Each &lt;code&gt;Slot&lt;/code&gt; render leaks ~15 bytes. Is this ideal? No. Does it compile? Yes. Is it the correct long-term solution? The correct long-term solution is a &lt;code&gt;Signal&amp;lt;String&amp;gt;&lt;/code&gt; prop type in input-rs, which is a future PR. For now: &lt;code&gt;Box::leak&lt;/code&gt; and move on.&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%2Fgumh6q6hvpzuttgh8yn4.jpeg" 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%2Fgumh6q6hvpzuttgh8yn4.jpeg" alt="this is fine" width="717" height="349"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Episode 3: The &lt;code&gt;as&lt;/code&gt; Cast That Broke Leptos
&lt;/h3&gt;

&lt;p&gt;The Leptos &lt;code&gt;view!&lt;/code&gt; macro cannot parse Rust cast expressions inline:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This fails to parse inside view!:&lt;/span&gt;
&lt;span class="n"&gt;validate_function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The macro sees the &lt;code&gt;as&lt;/code&gt; keyword and gets confused about what's a prop name vs. a type expression. The fix: extract to a &lt;code&gt;let&lt;/code&gt; binding &lt;strong&gt;before&lt;/strong&gt; the &lt;code&gt;view!&lt;/code&gt; call:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;always_valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// then inside view!:&lt;/span&gt;
&lt;span class="n"&gt;validate_function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;always_valid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Three lines in, five compilation cycles later. We hope this saves you ten minutes.&lt;/p&gt;
&lt;h3&gt;
  
  
  Episode 4: &lt;code&gt;String&lt;/code&gt; vs &lt;code&gt;&amp;amp;str&lt;/code&gt; in Dioxus &lt;code&gt;rsx!&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Dioxus's &lt;code&gt;rsx!&lt;/code&gt; macro is strict about attribute types. When &lt;code&gt;slot_class&lt;/code&gt; was a &lt;code&gt;String&lt;/code&gt;, the macro would refuse:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;format!("...", ...)&lt;/code&gt; produces a &lt;code&gt;String&lt;/code&gt;. Dioxus attributes want &lt;code&gt;&amp;amp;str&lt;/code&gt;. The same &lt;code&gt;Box::leak&lt;/code&gt; pattern solved this too:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;slot_class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;leak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="py"&gt;.variant&lt;/span&gt;&lt;span class="nf"&gt;.to_slot_class&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="py"&gt;.class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into_boxed_str&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;
  
  
  Episode 5: The Inter-Group Focus Traversal Collision
&lt;/h3&gt;

&lt;p&gt;Here is a fun brain teaser: what happens when you put &lt;em&gt;two&lt;/em&gt; OTP components on the exact same page, and you start typing in the second one?&lt;br&gt;
Well, since our slots were originally assigned hardcoded IDs like &lt;code&gt;otp-slot-0&lt;/code&gt;, &lt;code&gt;otp-slot-1&lt;/code&gt;, the moment you typed a character in the second instance, &lt;code&gt;document.getElementById("otp-slot-1")&lt;/code&gt; would aggressively hijack focus and yank your cursor all the way back up to the &lt;em&gt;first&lt;/em&gt; OTP component on the page.&lt;/p&gt;

&lt;p&gt;The fix? Prefixing every slot ID with a unique &lt;code&gt;instance_id&lt;/code&gt; minted from a global atomic counter (&lt;code&gt;OTP_INSTANCE_COUNTER.fetch_add(1, Ordering::Relaxed)&lt;/code&gt;). Now every widget lives in its own perfectly scoped focus namespace, free from neighborhood turf wars.&lt;/p&gt;
&lt;h3&gt;
  
  
  Episode 6: The "Sticky" Backspace (vDOM vs Physical DOM)
&lt;/h3&gt;

&lt;p&gt;Across Leptos and Yew we noticed a bizarre issue: if you typed a character, erased it, and tried typing again, the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; would refuse to update. Or if you filled the very last slot, the input component became "sticky" and refused to overwrite the final character.&lt;/p&gt;

&lt;p&gt;The root cause was a classic Virtual DOM vs Physical DOM standoff. We were setting the internal state to &lt;code&gt;""&lt;/code&gt;, but frameworks optimize their renders. Leptos &lt;code&gt;input-rs&lt;/code&gt; used a one-way, read-once initialization for &lt;code&gt;value=handle.0.get()&lt;/code&gt;. Yew assumed the string was already empty and ignored the reconciliation. Because the physical HTML &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; wasn't being forcefully synchronized, the raw DOM held onto the sticky character and choked out any new keystrokes.&lt;/p&gt;

&lt;p&gt;We had to bypass the frameworks entirely and manually flush the physical DOM element inside the keyboard event handlers using raw Web APIs (&lt;code&gt;input_ref.cast::&amp;lt;web_sys::HtmlInputElement&amp;gt;().unwrap().set_value("")&lt;/code&gt;). The lesson here? Sometimes the fastest way out of a reactive state desync is a direct, imperative smash to the physical DOM.&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%2F7amt7en2dkhidry7rkli.jpeg" 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%2F7amt7en2dkhidry7rkli.jpeg" alt="it keeps happening" width="660" height="379"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Keyboard Navigation
&lt;/h2&gt;

&lt;p&gt;One of the more satisfying pieces: full keyboard navigation across slots.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Any character key&lt;/strong&gt; → fills current slot, auto-advances focus to the next&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Backspace&lt;/code&gt;&lt;/strong&gt; → clears current slot; if already empty, goes to the previous slot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ArrowLeft&lt;/code&gt;&lt;/strong&gt; → jumps to previous slot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ArrowRight&lt;/code&gt;&lt;/strong&gt; → jumps to next slot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Tab&lt;/code&gt;&lt;/strong&gt; → advances naturally (browser default, we don't intercept)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this is handled in the &lt;code&gt;on_slot_keydown&lt;/code&gt; callback in the parent &lt;code&gt;Otp&lt;/code&gt; component, which uses &lt;code&gt;NodeRef&lt;/code&gt; (Yew) or the equivalent signal-based refs (Dioxus/Leptos) to imperatively &lt;code&gt;.focus()&lt;/code&gt; the target input.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Backspace"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// slot is already empty, go back&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slot_refs&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="py"&gt;.cast&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HtmlInputElement&lt;/span&gt;&lt;span class="o"&gt;&amp;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;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.focus&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No third-party focus-trap libraries. No jQuery. Pure DOM manipulation from Rust.&lt;/p&gt;
&lt;h2&gt;
  
  
  HOTP and TOTP Validation
&lt;/h2&gt;

&lt;p&gt;OTP RS ships RFC 4226 (HOTP) and RFC 6238 (TOTP) implementations using &lt;a href="https://crates.io/crates/totp-rs" rel="noopener noreferrer"&gt;&lt;code&gt;totp-rs&lt;/code&gt;&lt;/a&gt;. The SHA-1 HMAC is hand-rolled using the standard iterative block compression algorithm:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;validate_hotp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;OtpValidationError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hotp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;OtpValidationError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HotpMismatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can validate on complete:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;on_complete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nf"&gt;validate_hotp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"your-secret"&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;web_sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;console&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;log_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="s"&gt;"Valid!"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;web_sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;console&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;warn_1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{e:?}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;hotp()&lt;/code&gt; function also lets you generate the expected code if you need to display a hint in development. For the HOTP example in the landing page, the valid code for secret &lt;code&gt;JBSWY3DPEHPK3PXP&lt;/code&gt; at counter 0 is computed at runtime via &lt;code&gt;hotp(b"JBSWY3DPEHPK3PXP", 0, 6)&lt;/code&gt;, no hardcoding required.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Yew&lt;/span&gt;
cargo add otprs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add otprs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add otprs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cargo.toml&lt;/span&gt;
&lt;span class="py"&gt;otprs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"yew"&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 component ships its own CSS as inline styles computed from Rust. No separate stylesheet needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building OTP RS was a journey through the exact kind of subtle, cross-framework, cross-layer complexity that makes Rust Web development both rewarding and sometimes deeply frustrating. We fought the compiler more than once, discovered ways that browser defaults quietly break invisible design patterns, and shipped a &lt;code&gt;Box::leak&lt;/code&gt; we're not entirely proud of.&lt;/p&gt;

&lt;p&gt;But the result is solid: a composable, keyboard-navigable, RFC-compliant OTP input component that works identically across Yew, Dioxus, and Leptos, with zero JavaScript and enough ARIA to satisfy a WCAG auditor.&lt;/p&gt;

&lt;p&gt;The next time you're building a login flow in Rust WASM and you reach for a six-box code input, you don't have to write it from scratch anymore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://otp-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out" width="215" height="66"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/otprs" rel="noopener noreferrer"&gt;
        otprs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🔐 A highly customizable OTP component for WASM frameworks (Powered by Input RS).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🔐 OTP RS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/otprs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/99c979b578eac0caf385178102db5a682324271fa35878e410cbc97bf35c3b78/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f6f74707273" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/otprs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/605694ec18192e4e88b5a6d6d75324745591bf6e335f926f8dfd3435dcc511a3/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f6f74707273" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/459a3bd96f34d40adfa48f7ea9f148fe03e5601b8e88cc12ec7b48149a0a5f40/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f6f74707273"&gt;&lt;img src="https://camo.githubusercontent.com/459a3bd96f34d40adfa48f7ea9f148fe03e5601b8e88cc12ec7b48149a0a5f40/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f6f74707273" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a90d14c350ec66cb0b131f5826793f397b954ed4eeeaa002e4285d7ff7f1a54d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e39302532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/otprs/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Fotprs%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://otp-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://otp-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://otp-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible OTP (One-Time Password) input component for WASM frameworks: Yew, Dioxus, and Leptos.&lt;/p&gt;
&lt;p&gt;Supports animated per-slot digit entry with automatic focus traversal, &lt;code&gt;primary&lt;/code&gt; and &lt;code&gt;secondary&lt;/code&gt; visual variants, built-in HOTP/TOTP validation per RFC 4226 and RFC 6238, and full WCAG compliance.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why OTP RS?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control every attribute, class, style, variant, pattern, ARIA labels and more, on the outermost container, each group, each slot, and each separator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⌨ Smart Focus Management&lt;/strong&gt;: Typing a digit automatically advances focus. Backspace regresses focus. Arrow keys navigate left and right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✨ Animated Entry&lt;/strong&gt;: Each digit pops with a scale animation when entered, and a blinking caret is shown in the active empty slot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔐 Built-in Validation&lt;/strong&gt;: Validate against HOTP (RFC 4226) or TOTP (RFC 6238) using a pure-Rust implementation, no C, no…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/otprs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>rust</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>📋 Form RS: Production-Ready Form Components for WASM Frameworks</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 04 Oct 2026 11:24:25 +0000</pubDate>
      <link>https://dev.to/wiseai/form-rs-production-ready-form-components-for-wasm-frameworks-4c03</link>
      <guid>https://dev.to/wiseai/form-rs-production-ready-form-components-for-wasm-frameworks-4c03</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Salut 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If there's one thing that unites frontend developers across every language, framework, and decade of web history, it's a deep, personal, somewhat traumatic relationship with HTML forms.&lt;/p&gt;

&lt;p&gt;You know the drill. You write a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;. You add an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;. You add a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;. You write the JavaScript to validate it on &lt;code&gt;blur&lt;/code&gt;. You add a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; for the error message. You wire up &lt;code&gt;aria-describedby&lt;/code&gt; so screen readers can find the error. You set &lt;code&gt;aria-invalid&lt;/code&gt; on the input. You set &lt;code&gt;aria-required&lt;/code&gt;. You check &lt;code&gt;event.preventDefault()&lt;/code&gt;. You realize you've been writing a custom form library for the last four hours. You consider leaving the industry.&lt;/p&gt;

&lt;p&gt;That stops today. We're shipping &lt;a href="https://github.com/opensass/form-rs" rel="noopener noreferrer"&gt;&lt;strong&gt;Form RS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What Is Form RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Form RS&lt;/strong&gt; is a fully composable, WCAG 2.2 AA compliant, production-ready form component library for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. It wraps &lt;a href="https://github.com/opensass/input-rs" rel="noopener noreferrer"&gt;&lt;strong&gt;Input RS&lt;/strong&gt;&lt;/a&gt; for the actual &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; rendering, provides a complete context-driven architecture for validation state propagation, and ships seven discrete components that you can mix freely.&lt;/p&gt;

&lt;p&gt;Think of it as the form library you would build yourself if you had time, patience, and hadn't already burned both writing &lt;code&gt;&amp;lt;div class="form-group"&amp;gt;&lt;/code&gt; for the 8000th time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Seven Components
&lt;/h2&gt;

&lt;p&gt;Form RS ships a composable hierarchy, not a monolith.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Form&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The outermost container. Wraps &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; with configurable &lt;code&gt;method&lt;/code&gt;, &lt;code&gt;action&lt;/code&gt;, &lt;code&gt;enctype&lt;/code&gt;, &lt;code&gt;autocomplete&lt;/code&gt;, ARIA labels, and submit/reset/invalid callbacks. There are two validation modes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;ValidationBehavior&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Native&lt;/span&gt;   &lt;span class="c1"&gt;// HTML5 + browser popups (default)&lt;/span&gt;
&lt;span class="nn"&gt;ValidationBehavior&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Aria&lt;/span&gt;     &lt;span class="c1"&gt;// Real-time ARIA errors, no popups, submit never blocked&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Control&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The context provider. Wraps a single field, distributes &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;focused&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt;, &lt;code&gt;variant&lt;/code&gt;, &lt;code&gt;color&lt;/code&gt;, and &lt;code&gt;size&lt;/code&gt; state to every child that reads &lt;code&gt;FormControlContext&lt;/code&gt;. Your labels and helper text automatically inherit this state without prop drilling.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Label&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Renders a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; that visually and semantically tracks the control's state. It goes red when there's an error. It glows when focused. It shows the required asterisk automatically. You don't have to think about any of this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In Yew:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="n"&gt;html_for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;focused&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;false&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="s"&gt;"Email address"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Helper&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; element below the input. Changes color based on validation state:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Helper&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;true&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="s"&gt;"Not a valid email."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Helper&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;true&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="s"&gt;"Looks great!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Three states, zero class strings.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Group&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Groups related checkboxes or radio buttons in a &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt;-adjacent &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;. The &lt;code&gt;row&lt;/code&gt; prop flips the layout from column to horizontal. The &lt;code&gt;aria_label&lt;/code&gt; wires up a &lt;code&gt;role="group"&lt;/code&gt; for screen readers.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;ControlLabel&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Wraps a form control (checkbox, radio, switch) with its associated label text. Controls label placement (&lt;code&gt;End&lt;/code&gt;, &lt;code&gt;Start&lt;/code&gt;, &lt;code&gt;Top&lt;/code&gt;, &lt;code&gt;Bottom&lt;/code&gt;), required asterisks, and disabled styling.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ControlLabel&lt;/span&gt;
    &lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Email notifications"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="n"&gt;label_placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;LabelPlacement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;End&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Field&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is the one you'll use most. A drop-in composition of &lt;code&gt;Control + Label + Input + Helper&lt;/code&gt; with reactive focus rings, error/valid ring states, ARIA attributes, and helper text management.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
    &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Email address"&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
    &lt;span class="n"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ferris@opensass.org"&lt;/span&gt;
    &lt;span class="n"&gt;helper_text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter a valid email."&lt;/span&gt;
    &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;full_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="n"&gt;valid_handle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;email_valid&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="n"&gt;validate_function&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validate_email&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One component. Fully wired. WCAG compliant. You're done.&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%2Fiiezjh4vh6gcpbgmns6h.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%2Fiiezjh4vh6gcpbgmns6h.png" alt="it just works" width="683" height="366"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Validation Architecture
&lt;/h2&gt;

&lt;p&gt;Form RS supports two distinct validation paradigms:&lt;/p&gt;
&lt;h3&gt;
  
  
  Native HTML5 Validation
&lt;/h3&gt;

&lt;p&gt;Uses browser-native &lt;code&gt;required&lt;/code&gt;, &lt;code&gt;pattern&lt;/code&gt;, &lt;code&gt;minlength&lt;/code&gt;, &lt;code&gt;maxlength&lt;/code&gt;, and &lt;code&gt;type="email"&lt;/code&gt; constraints. The browser handles error messages. Form submission is blocked on invalid fields. This is the &lt;code&gt;ValidationBehavior::Native&lt;/code&gt; default.&lt;/p&gt;
&lt;h3&gt;
  
  
  External/ARIA Validation
&lt;/h3&gt;

&lt;p&gt;Pass a &lt;code&gt;ValidationState&lt;/code&gt; explicitly, from a server response, a complex cross-field rule, or your own logic:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;ValidationState&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;        &lt;span class="c1"&gt;// No judgment, untouched&lt;/span&gt;
&lt;span class="nn"&gt;ValidationState&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt;       &lt;span class="c1"&gt;// Green ring, success helper text&lt;/span&gt;
&lt;span class="nn"&gt;ValidationState&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="c1"&gt;// Red ring, error helper text, aria-invalid="true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Server errors? Set &lt;code&gt;validation_state={ValidationState::Invalid("Email already in use.".into())}&lt;/code&gt; on the field. The error surfaces immediately. The ARIA is correct. Done.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessibility Built In
&lt;/h2&gt;

&lt;p&gt;This isn't "we added aria-label" accessibility. This is the real thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every &lt;code&gt;Field&lt;/code&gt; generates a unique &lt;code&gt;{id}-helper&lt;/code&gt; element ID and passes it as &lt;code&gt;aria-describedby&lt;/code&gt; on the underlying &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-required&lt;/code&gt; and &lt;code&gt;aria-invalid&lt;/code&gt; are set precisely based on prop + validation state, not just "always true".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Helper&lt;/code&gt; renders with &lt;code&gt;role="alert"&lt;/code&gt; when in error state, so screen reader users hear errors without tabbing to them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Label&lt;/code&gt; is always linked to its input via &lt;code&gt;for&lt;/code&gt;/&lt;code&gt;html_for&lt;/code&gt;. No floating labels that break semantics.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Group&lt;/code&gt; propagates &lt;code&gt;role="group"&lt;/code&gt; with &lt;code&gt;aria-label&lt;/code&gt; for checkbox/radio clusters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Audit-passing HTML forms. In Rust. Across three WASM frameworks.&lt;/p&gt;
&lt;h2&gt;
  
  
  The &lt;code&gt;ValidationState&lt;/code&gt; Pattern
&lt;/h2&gt;

&lt;p&gt;This is the piece that makes server-side validation ergonomic:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;ValidationState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Valid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;Invalid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&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;Pass &lt;code&gt;None&lt;/code&gt; on a fresh field. Pass &lt;code&gt;Valid&lt;/code&gt; once you've confirmed on the backend. Pass &lt;code&gt;Invalid&lt;/code&gt; with your error message string when the server rejects it. The component does the rest.&lt;/p&gt;
&lt;h2&gt;
  
  
  Variant, Color, and Size System
&lt;/h2&gt;

&lt;p&gt;Form RS exposes a full semantic token system for the input appearance:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Visual input style&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Outlined&lt;/span&gt;  &lt;span class="c1"&gt;// Default, bordered input box&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Filled&lt;/span&gt;    &lt;span class="c1"&gt;// Solid filled background&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Standard&lt;/span&gt;  &lt;span class="c1"&gt;// Bottom-border only&lt;/span&gt;

&lt;span class="c1"&gt;// Accent color (rings, labels, helper text)&lt;/span&gt;
&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Primary&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Secondary&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;

&lt;span class="c1"&gt;// Input density&lt;/span&gt;
&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Small&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Medium&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Building a dense admin data-entry form? &lt;code&gt;Size::Small&lt;/code&gt;. Consumer onboarding flow? &lt;code&gt;Size::Medium&lt;/code&gt;. Dark theme with error highlights? &lt;code&gt;Color::Error&lt;/code&gt;. The system handles the visual output; you just name the intent.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;

&lt;p&gt;Stop writing raw HTML form boilerplate. Do this:&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="c"&gt;# Yew&lt;/span&gt;
cargo add form-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add form-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add form-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;Forms are foundational. Every user interaction that matters, login, registration, checkout, profile editing, contact, search, flows through a form. Getting them right means getting ARIA right, validation right, focus state right, and error surfacing right. Every time. On every field.&lt;/p&gt;

&lt;p&gt;Form RS is the answer to "who has time for all of that." We did. You don't have to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://form-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out" width="215" height="66"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/form-rs" rel="noopener noreferrer"&gt;
        form-rs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      📋 A highly customizable Form component for WASM frameworks (Powered by Input RS).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;📋 Form RS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/form-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/914def72e9822842f27ce04ffbe02abeb937ac8a292eebca685b30adcd902eed/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f666f726d2d7273" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/form-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/baea95c455274af1eb77ab50feaa5a0ca76934a046ecdbcaa0387a463856b143/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f666f726d2d7273" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/24654307ae01cacd5f0ed9b82e587918acb5fc25eb5cdf7e36961991633598b1/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f666f726d2d7273"&gt;&lt;img src="https://camo.githubusercontent.com/24654307ae01cacd5f0ed9b82e587918acb5fc25eb5cdf7e36961991633598b1/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f666f726d2d7273" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/31c82dd347f4da3b0ee4fb00bdbab1450d962c202a7f1d46feeb52cb06c634fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e38392532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/form-rs/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Fform-rs%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://form-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://form-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://form-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible form component library for WASM frameworks: Yew, Dioxus, and Leptos.
Supports HTML5 and ARIA validation, composable sub-components (&lt;code&gt;Form&lt;/code&gt;, &lt;code&gt;Control&lt;/code&gt;, &lt;code&gt;FormLabel&lt;/code&gt;,
&lt;code&gt;Helper&lt;/code&gt;, &lt;code&gt;Group&lt;/code&gt;, &lt;code&gt;ControlLabel&lt;/code&gt;, &lt;code&gt;Field&lt;/code&gt;), and full WCAG 2.2 AA compliance.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why Form RS?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control variant, color, size, class, style, ARIA labels, and every sub-component attribute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧩 Composable API&lt;/strong&gt;: Mix &lt;code&gt;Form&lt;/code&gt;, &lt;code&gt;Control&lt;/code&gt;, &lt;code&gt;FormLabel&lt;/code&gt;, &lt;code&gt;Helper&lt;/code&gt;, &lt;code&gt;Group&lt;/code&gt;, &lt;code&gt;ControlLabel&lt;/code&gt;, and &lt;code&gt;Field&lt;/code&gt; independently or together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✅ Dual Validation&lt;/strong&gt;: Supports native HTML5 validation and real-time ARIA error messaging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;♿ Accessible by Default&lt;/strong&gt;: &lt;code&gt;aria-describedby&lt;/code&gt;, &lt;code&gt;aria-required&lt;/code&gt;, &lt;code&gt;aria-invalid&lt;/code&gt;, and &lt;code&gt;role="alert"&lt;/code&gt; wired up automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔧 Framework Agnostic&lt;/strong&gt;: Same API semantics across Yew, Dioxus, and Leptos.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Y Yew Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/form-rs/blob/main/YEW.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/form-rs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>rust</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🖥️ Code RS: CDN-Free Syntax-Highlighted Code Components for WASM</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 04 Oct 2026 11:24:17 +0000</pubDate>
      <link>https://dev.to/wiseai/code-rs-cdn-free-syntax-highlighted-code-components-for-wasm-njc</link>
      <guid>https://dev.to/wiseai/code-rs-cdn-free-syntax-highlighted-code-components-for-wasm-njc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Privyet 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You know that moment when you paste a &lt;code&gt;&amp;lt;pre&amp;gt;&amp;lt;code&amp;gt;&lt;/code&gt; block into your app and it looks like it was styled in 2003 by someone who had just discovered &lt;code&gt;color: green&lt;/code&gt;? No theme. No copy button. No language badge. Just raw, uncolored text sitting in a box that someone called "good enough"?&lt;/p&gt;

&lt;p&gt;Yeah. We fixed that. Today we're shipping &lt;a href="https://github.com/opensass/coders" rel="noopener noreferrer"&gt;&lt;strong&gt;Code RS&lt;/strong&gt;&lt;/a&gt;.&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%2F5p3yzfxcd12l7l45st9y.jpeg" 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%2F5p3yzfxcd12l7l45st9y.jpeg" alt="One does not simply"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Code RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code RS&lt;/strong&gt; is a production-ready, fully-themed, accessible code display component for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. It does everything the ecosystem was missing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inline &lt;code&gt;&amp;lt;Code&amp;gt;&lt;/code&gt;&lt;/strong&gt;: colored, sized, variant-aware, with ARIA semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;&amp;lt;Block&amp;gt;&lt;/code&gt;&lt;/strong&gt;: a composable container with header, title, language badge, copy trigger, and scrollable content area.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure-Rust syntax highlighting&lt;/strong&gt;: zero CDN, zero JavaScript, compiles to clean WASM, 20+ languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 built-in themes&lt;/strong&gt;: OneDark, Dracula, NightOwl, GitHub Dark/Light, Solarized, Monokai, Nord, all switchable via a single &lt;code&gt;theme&lt;/code&gt; prop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No Prism.js. No highlight.js. No 10MB script tag loaded from a CDN you definitely trust completely. Just Rust, bytes, and inline &lt;code&gt;style=&lt;/code&gt; spans.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Big Idea
&lt;/h2&gt;

&lt;p&gt;Here's the thing about syntax highlighting in WASM apps: every existing solution assumes JavaScript. Prism.js needs a DOM. highlight.js needs a runtime. Shiki needs Node. Tree-sitter is great, but it weighs as much as a sedan.&lt;/p&gt;

&lt;p&gt;So we wrote our own.&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%2Fmanuf7qi630dqih250ak.jpeg" 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%2Fmanuf7qi630dqih250ak.jpeg" alt="Pure-Rust tokenizer, no biggie"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;highlight_code(code, lang, theme)&lt;/code&gt; function in &lt;code&gt;common.rs&lt;/code&gt; is a hand-rolled, char-by-char tokenizer that handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block comments (&lt;code&gt;/* */&lt;/code&gt;), single-line comments (&lt;code&gt;//&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;--&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Double/single-quoted strings and JS template literals&lt;/li&gt;
&lt;li&gt;Hex and float number literals with suffixes (&lt;code&gt;0xFF&lt;/code&gt;, &lt;code&gt;1.0f32&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Rust macros (&lt;code&gt;println!&lt;/code&gt;, &lt;code&gt;vec!&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Python/CSS decorators (&lt;code&gt;@dataclass&lt;/code&gt;, &lt;code&gt;@media&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HTML tag names (&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;/span&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;PascalCase → type, ALL_CAPS → constant, &lt;code&gt;ident(&lt;/code&gt; → function call&lt;/li&gt;
&lt;li&gt;Language-specific keyword sets (Rust, Python, TypeScript, SQL, Bash, 16 more)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All token spans get &lt;strong&gt;inline &lt;code&gt;style=&lt;/code&gt; attributes&lt;/strong&gt; from the chosen theme. No CSS classes. No external stylesheet. Just &lt;code&gt;&amp;lt;span style="color:#c678dd;font-weight:600"&amp;gt;fn&amp;lt;/span&amp;gt;&lt;/code&gt;, and it works everywhere, including iframes and shadow DOM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;coders&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlight_code&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;highlight_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fn main() {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    println!(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rust&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Dracula&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → "&amp;lt;span style="color:#ff79c6;font-weight:600"&amp;gt;fn&amp;lt;/span&amp;gt; ..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Code&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The simplest unit. A &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; element with color, variant, and size props.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Yew&lt;/span&gt;
&lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Subtle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sm&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="s"&gt;"console.log(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Hello, world!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="o"&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;Variants work exactly as you'd expect from the rest of Open SASS Kit: &lt;code&gt;Solid&lt;/code&gt;, &lt;code&gt;Subtle&lt;/code&gt;, &lt;code&gt;Outline&lt;/code&gt;, &lt;code&gt;Surface&lt;/code&gt;, &lt;code&gt;Plain&lt;/code&gt;. Colors are the full palette: &lt;code&gt;Default&lt;/code&gt;, &lt;code&gt;Red&lt;/code&gt;, &lt;code&gt;Orange&lt;/code&gt;, &lt;code&gt;Yellow&lt;/code&gt;, &lt;code&gt;Green&lt;/code&gt;, &lt;code&gt;Teal&lt;/code&gt;, &lt;code&gt;Accent&lt;/code&gt;, &lt;code&gt;Pink&lt;/code&gt;, &lt;code&gt;Success&lt;/code&gt;, &lt;code&gt;Warning&lt;/code&gt;, &lt;code&gt;Danger&lt;/code&gt;, and &lt;code&gt;Custom("your-inline-css")&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Block&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Leptos&lt;/span&gt;
&lt;span class="nd"&gt;view!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Block&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fn main() {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    println!(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;}"&lt;/span&gt;
        &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rust&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Theme&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NightOwl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;"main.rs"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LanguageBadge&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CopyTrigger&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Block&lt;/span&gt;&lt;span class="o"&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;The &lt;code&gt;Block&lt;/code&gt; pushes a &lt;code&gt;BlockContext&lt;/code&gt; containing &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;language&lt;/code&gt;, and &lt;code&gt;theme&lt;/code&gt; into a provider tree. All child components read from context. &lt;code&gt;Content&lt;/code&gt; calls &lt;code&gt;highlight_code&lt;/code&gt; and injects the result via &lt;code&gt;inner_html&lt;/code&gt; / &lt;code&gt;dangerous_inner_html&lt;/code&gt; / &lt;code&gt;Html::from_html_unchecked&lt;/code&gt;, the framework-appropriate unsafe-but-correct escape hatch for pre-rendered HTML. No prop drilling. No callback chains. Just context.&lt;/p&gt;
&lt;h2&gt;
  
  
  8 Themes
&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%2F4d6ty5vtj0lt7in1kdso.jpeg" 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%2F4d6ty5vtj0lt7in1kdso.jpeg" alt="Just right"&gt;&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;Theme&lt;/th&gt;
&lt;th&gt;Background&lt;/th&gt;
&lt;th&gt;Vibe&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OneDark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#1a1a2e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The classic. Atom's gift to the world.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Dracula&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#282a36&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Halloween every day. Pink keywords.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NightOwl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#011627&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deep blue, warm salmon numbers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GithubDark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#0d1117&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Feels like GitHub, because it is.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GithubLight&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#ffffff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;For those who dare use light mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Solarized&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#002b36&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ethan Schoonover's gift to the terminal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Monokai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#272822&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Sublime Text nostalgia trip.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Nord&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#2e3440&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Arctic. Clean. Borderline peaceful.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Switch themes at runtime by simply changing the &lt;code&gt;theme&lt;/code&gt; prop. The &lt;code&gt;ThemeColors&lt;/code&gt; struct drives inline style generation, every &lt;code&gt;push_span()&lt;/code&gt; call pulls the exact CSS value from the active theme's fields.&lt;/p&gt;

&lt;p&gt;Need your brand colors? &lt;code&gt;Theme::Custom(ThemeColors { keyword: "color:#ff0099;font-weight:600", ... })&lt;/code&gt; and you're done.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Build Journey
&lt;/h2&gt;

&lt;p&gt;We are not going to pretend this was a relaxing weekend project. Here is an honest accounting.&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%2Fsxyw4cyx4pq74mywzcze.jpeg" 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%2Fsxyw4cyx4pq74mywzcze.jpeg" alt="Expectations vs Reality"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Chapter 1: The Rust 2024 Edition
&lt;/h3&gt;

&lt;p&gt;Rust Edition 2024 changed how string-like identifiers in macro positions are parsed. The &lt;code&gt;yew::html!&lt;/code&gt; macro started rejecting class names like &lt;code&gt;text-black&lt;/code&gt; and &lt;code&gt;whitespace-pre&lt;/code&gt;, specifically the hyphen-adjacent tokens that look like prefix expressions.&lt;/p&gt;

&lt;p&gt;The error: &lt;code&gt;prefix 'black' is unknown&lt;/code&gt;. The fix: add a trailing space after the class name. Simple, but it wasted an embarrassing amount of time because the error message looks nothing like what it actually is.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (breaks in Edition 2024):&lt;/span&gt;
&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex text-black"&lt;/span&gt;
&lt;span class="c1"&gt;// After:&lt;/span&gt;
&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex text-black "&lt;/span&gt;  &lt;span class="c1"&gt;// ← single space, problem solved&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Chapter 2: Dioxus RSX
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rsx!&lt;/code&gt; macro in Dioxus parses string prop values as format strings. So this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"fn main() {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    println!(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Explodes with &lt;code&gt;Failed to parse formatted segment: Expected Ident or Exp&lt;/code&gt;. Because &lt;code&gt;{&lt;/code&gt; inside a string prop is format syntax to Dioxus, not a literal curly brace.&lt;/p&gt;

&lt;p&gt;The fix: extract all code strings to &lt;code&gt;const&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HELLO_WORLD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"fn main() {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    println!(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;rsx!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Block&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HELLO_WORLD&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;Unglamorous? Yes. But it compiles.&lt;/p&gt;
&lt;h3&gt;
  
  
  Chapter 3: The &lt;code&gt;dangerous_inner_html&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In Dioxus, &lt;code&gt;dangerous_inner_html&lt;/code&gt; takes ownership of a &lt;code&gt;String&lt;/code&gt;. In Leptos, &lt;code&gt;inner_html&lt;/code&gt; takes a &lt;code&gt;&amp;amp;str&lt;/code&gt;. In Yew, &lt;code&gt;Html::from_html_unchecked&lt;/code&gt; takes an &lt;code&gt;AttrValue&lt;/code&gt;. Three frameworks, three signatures, three slightly different ways to inject a pre-rendered HTML string.&lt;/p&gt;

&lt;p&gt;Each one worked fine once you knew the exact type expected. Getting there required reading the framework source, not the docs, because the docs had helpfully omitted the borrow semantics.&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%2Fkx1qo7k9qkr2x1cw51ob.jpeg" 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%2Fkx1qo7k9qkr2x1cw51ob.jpeg" alt="Fine dababy"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Chapter 4: Non-Exhaustive &lt;code&gt;Variant::Custom&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Adding &lt;code&gt;Custom(&amp;amp;'static str)&lt;/code&gt; to the &lt;code&gt;Variant&lt;/code&gt; enum immediately broke every match in all three &lt;code&gt;Code&lt;/code&gt; component implementations. Expected. Annoying. The fix is the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But finding all three match sites across three files while also trying to fix four other things simultaneously is exactly the kind of thing that makes you wish Rust had &lt;code&gt;#[non_exhaustive]&lt;/code&gt; as an opt-in marker you could flip during development.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessibility
&lt;/h2&gt;

&lt;p&gt;Code RS ships accessible markup out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Block&lt;/code&gt; renders as &lt;code&gt;&amp;lt;figure role="region"&amp;gt;&lt;/code&gt; with &lt;code&gt;aria-label&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The inner &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; gets &lt;code&gt;tabindex="0"&lt;/code&gt; so keyboard users can scroll it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CopyTrigger&lt;/code&gt; carries &lt;code&gt;aria-label="Copy code to clipboard"&lt;/code&gt; and &lt;code&gt;aria-live&lt;/code&gt; region feedback via the copied label swap.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Code&lt;/code&gt; accepts &lt;code&gt;aria_label&lt;/code&gt; for use in contexts where &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; alone doesn't carry enough meaning.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LanguageBadge&lt;/code&gt; reads the language from context and renders &lt;code&gt;aria-label="Language: rust"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Screen readers don't need to guess what anything is.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Yew&lt;/span&gt;
cargo add coders &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add coders &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add coders &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. The syntax highlighting, theming, clipboard, and accessibility, all included. No config files. No CSS imports. No &lt;code&gt;npm install @something/highlighter-peer-dependency&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Writing a CDN-free, pure-WASM syntax highlighter from scratch to ship alongside a composable code block component is not the most efficient path. But it's the correct one for this ecosystem.&lt;/p&gt;

&lt;p&gt;The web has enough &lt;code&gt;&amp;lt;script src="https://cdn.example.com/dep.min.js"&amp;gt;&lt;/code&gt; tags. Rust WASM doesn't need to inherit that habit.&lt;/p&gt;

&lt;p&gt;Code RS compiles to WASM, highlights code inline, and ships 8 themes without a single network request beyond your app bundle. That's the promise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://code-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/coders" rel="noopener noreferrer"&gt;
        coders
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      💻 A highly customizable code component for WASM frameworks.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;💻 Code RS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/coders" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/080837a72b46befa0fe601eb51c45056406bcfd34d3ad958d75a93d7018ca951/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f636f64657273" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/coders" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/951633484351026d612af79011b5eeae3b1e1c6580885f1084fb138e5ac87879/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f636f64657273" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/581a82e93aeccae36e646c4b776cf252912f9f7dd4c5a0890341efd64aa7600d/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f636f64657273"&gt;&lt;img src="https://camo.githubusercontent.com/581a82e93aeccae36e646c4b776cf252912f9f7dd4c5a0890341efd64aa7600d/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f636f64657273" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/31c82dd347f4da3b0ee4fb00bdbab1450d962c202a7f1d46feeb52cb06c634fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e38392532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/coders/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Fcoders%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://code-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://code-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://code-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible inline code and code-block component for WASM frameworks: Yew, Dioxus, and Leptos. Supports multiple colors, variants, sizes, copy-to-clipboard, and composable sub-components, all WCAG compliant.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why Code RS?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control every attribute, class, style, color, variant, size, ARIA labels, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📋 Copy to Clipboard&lt;/strong&gt;: Built-in copy button with a configurable confirmation label and reset timeout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧩 Composable&lt;/strong&gt;: Compose &lt;code&gt;Header&lt;/code&gt;, &lt;code&gt;Title&lt;/code&gt;, &lt;code&gt;CopyTrigger&lt;/code&gt;, &lt;code&gt;Content&lt;/code&gt;, and &lt;code&gt;LanguageBadge&lt;/code&gt; independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;♿ Accessible by Default&lt;/strong&gt;: &lt;code&gt;role="region"&lt;/code&gt;, &lt;code&gt;aria-label&lt;/code&gt;, &lt;code&gt;aria-live&lt;/code&gt; and &lt;code&gt;tabindex&lt;/code&gt; wired up automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔧 Framework Agnostic&lt;/strong&gt;: Same API semantics across Yew, Dioxus, and Leptos.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Y Yew Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/coders/blob/main/YEW.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Yew app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🧬 Dioxus Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/coders/blob/main/DIOXUS.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Dioxus app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌱&lt;/h2&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/coders" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>rust</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🃏 Card RS: Extremely Customizable Card component for WASM frameworks</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 27 Sep 2026 11:11:08 +0000</pubDate>
      <link>https://dev.to/wiseai/card-rs-extremely-customizable-card-component-for-wasm-frameworks-1j0c</link>
      <guid>https://dev.to/wiseai/card-rs-extremely-customizable-card-component-for-wasm-frameworks-1j0c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Salut tout le monde 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If there is one layout component that has been re-implemented more times than the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, it's the Card. Think about it. Every widget, every dashboard panel, every pricing tier, every shiny glowing glassmorphism element you've ever seen is, deep down, a card.&lt;/p&gt;

&lt;p&gt;Instead of writing &lt;code&gt;div class="p-6 border rounded-xl shadow-lg bg-white"&lt;/code&gt; for the 5000th time, we decided to solve cards natively for WASM.&lt;/p&gt;

&lt;p&gt;Today, we're shipping &lt;a href="https://github.com/opensass/card-rs" rel="noopener noreferrer"&gt;&lt;strong&gt;Card RS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Card RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Card RS&lt;/strong&gt; is an extremely customizable, production-ready, accessible Card component for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. We've extracted all the tedious BEM boilerplate, flexbox wrangling, and ARIA attributes out of your templates, giving you a clean, composable API for building solid UI surfaces.&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%2Fvu3cf63zifl903lhoc80.jpeg" 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%2Fvu3cf63zifl903lhoc80.jpeg" alt="Oprah" width="620" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cards shouldn't be monoliths. If you just need a surface, &lt;code&gt;&amp;lt;Card&amp;gt;&lt;/code&gt; works perfectly alone. If you need standard anatomical parts, stick &lt;code&gt;&amp;lt;Header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Title&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Content&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Footer&amp;gt;&lt;/code&gt; in there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Composable Anatomy
&lt;/h2&gt;

&lt;p&gt;The problem with most UI library cards is that they force you into a specific layout. Card RS doesn't mandate structure; it provides logical boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Shell: &lt;code&gt;Card&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The parent wrapper. It renders a clean HTML5 &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; (or whatever ARIA role you need) with our default elevated styling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;card_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;card_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[function_component(MyWidget)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_labelledby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"widget-title"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="c1"&gt;// the world is yours in here&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="o"&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;h3&gt;
  
  
  The Skeleton: Headers, Content, &amp;amp; Footers
&lt;/h3&gt;

&lt;p&gt;Don't want to write inline styles for gaps and flex-columns? Neither do we.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;aria_labelledby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"c-title"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"c-title"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Card Title"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"The description lives here."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Any content fits neatly in the main body area."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Footer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="n"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Confirm"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Confirm"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Footer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The header stacks title and description with precise spacing. The footer handles your action bars. Everything just snaps into place like LEGOs.&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%2F8ljo5nnra85a7muehcx5.jpeg" 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%2F8ljo5nnra85a7muehcx5.jpeg" alt="A perfectly aligned card component" width="444" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Variants and Prominence
&lt;/h2&gt;

&lt;p&gt;Not all cards are created equal. You need visual hierarchy. We provide a &lt;code&gt;Variant&lt;/code&gt; matrix that affects the surface depth and contrast without rewriting class strings.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Variant&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Transparent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// No background, merges with the canvas&lt;/span&gt;
    &lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Standard surface layer&lt;/span&gt;
    &lt;span class="n"&gt;Secondary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Elevated and highlighted&lt;/span&gt;
    &lt;span class="n"&gt;Tertiary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Premium prominence (perfect for selected items)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Building an interactive pricing selector? Wrap your iterations in a &lt;code&gt;&amp;lt;Card variant={if selected { Variant::Secondary } else { Variant::Default }}&amp;gt;&lt;/code&gt; and your hierarchy logic is done.&lt;/p&gt;
&lt;h2&gt;
  
  
  Framework Parity
&lt;/h2&gt;

&lt;p&gt;Like everything we build, &lt;strong&gt;Card RS&lt;/strong&gt; provides identical API surfaces and behavioral guarantees across all three rusty frontends:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Yew&lt;/th&gt;
&lt;th&gt;Dioxus&lt;/th&gt;
&lt;th&gt;Leptos&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Card&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Header&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Title&lt;/code&gt; &amp;amp; &lt;code&gt;Description&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Content&lt;/code&gt; &amp;amp; &lt;code&gt;Footer&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variant Matrix&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessible ARIA bindings&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Role overrides&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you know how to build a card in Leptos, you can build a card in Dioxus. The props are the same. The BEM classes are the same. The logic is identical.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessibility Built-In
&lt;/h2&gt;

&lt;p&gt;Accessible surfaces are often completely ignored by developers until an audit fails. &lt;strong&gt;Card RS&lt;/strong&gt; is designed strictly around WCAG guidelines.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Card&lt;/code&gt; renders with &lt;code&gt;role="article"&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;We enforce &lt;code&gt;aria_labelledby&lt;/code&gt; to tie structural landmarks to the &lt;code&gt;Title&lt;/code&gt; ID.&lt;/li&gt;
&lt;li&gt;If you want a non-interactive surface, just override it with &lt;code&gt;role="note"&lt;/code&gt; or &lt;code&gt;role="region"&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Accessible structural linking:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;aria_labelledby&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"promo-heading"&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"region"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"promo-heading"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Special Offer!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With one prop, screen readers will now announce "Region: Special Offer!" properly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;We aren't trapping you in our aesthetic. Want a weird horizontally-aligned flex-row card with a gradient background? Just use the &lt;code&gt;style&lt;/code&gt; prop. Card RS accepts your CSS strings eagerly.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;

&lt;p&gt;Stop copying and pasting giant Tailwind HTML blobs. Do this instead:&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="c"&gt;# Yew&lt;/span&gt;
cargo add card-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add card-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add card-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;The web is made of cards. Taking the time to unify how we create, structure, and render them across Wasm frameworks means we can stop fighting with padding and flexbox alignment, and get back to building real features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://card-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out" width="215" height="66"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/card-rs" rel="noopener noreferrer"&gt;
        card-rs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🃏 A highly customizable card component for WASM frameworks
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🃏 Card RS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/card-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/aec4d66c1d0cd22f203c1693dffa539fdcd1c4dda9548c3093c862ad2163ffd2/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f636172642d7273" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/card-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/05a0e33232aa5c81b38cf2783119f721dae363ffefe6bfb20fe7d99df024d69d/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f636172642d7273" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/acb28f424a370815c5e608ac242d84568744323542f9dd96477cf3634b73be26/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f636172642d7273"&gt;&lt;img src="https://camo.githubusercontent.com/acb28f424a370815c5e608ac242d84568744323542f9dd96477cf3634b73be26/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f636172642d7273" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/31c82dd347f4da3b0ee4fb00bdbab1450d962c202a7f1d46feeb52cb06c634fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e38392532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/card-rs/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Fcard-rs%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://card-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://card-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://card-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible card component for WASM frameworks: Yew, Dioxus, and Leptos.
Supports semantic prominence variants, composable sub-components (header, title, description,
content, footer), and full WCAG compliance.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why Card RS?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control variant, class, style, ARIA labels, and every sub-component attribute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧩 Composable API&lt;/strong&gt;: Use &lt;code&gt;Card&lt;/code&gt;, &lt;code&gt;Header&lt;/code&gt;, &lt;code&gt;Title&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, &lt;code&gt;Content&lt;/code&gt;, and &lt;code&gt;Footer&lt;/code&gt; independently or together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🏷️ Semantic Variants&lt;/strong&gt;: &lt;code&gt;transparent&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;secondary&lt;/code&gt;, &lt;code&gt;tertiary&lt;/code&gt;, themes interpret prominence without hard-coded colors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;♿ Accessible by Default&lt;/strong&gt;: &lt;code&gt;role="article"&lt;/code&gt;, &lt;code&gt;aria-labelledby&lt;/code&gt;, and &lt;code&gt;aria-label&lt;/code&gt; wired up automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔧 Framework Agnostic&lt;/strong&gt;: Same API semantics across Yew, Dioxus, and Leptos.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Y Yew Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/card-rs/blob/main/YEW.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Yew app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🧬 Dioxus Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/card-rs/blob/main/DIOXUS.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/card-rs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>rust</category>
      <category>webdev</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔴 Badge RS: Easy to Use Badge Components for WASM Frameworks</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 27 Sep 2026 11:08:44 +0000</pubDate>
      <link>https://dev.to/wiseai/badge-rs-easy-to-use-badge-components-for-wasm-frameworks-4p3k</link>
      <guid>https://dev.to/wiseai/badge-rs-easy-to-use-badge-components-for-wasm-frameworks-4p3k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Je vous salue 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every WASM app eventually needs a badge. The little red circle on your notification bell. The green dot on the corner of an avatar. The "99+" that taunts you every morning from the inbox icon. They're everywhere, and somehow everyone is still hand-rolling them.&lt;/p&gt;

&lt;p&gt;That stops today. We're shipping &lt;a href="https://github.com/opensass/badges-rs" rel="noopener noreferrer"&gt;&lt;strong&gt;Badge RS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Badge RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Badge RS&lt;/strong&gt; is a production-ready badge component for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. Notification counters, status dots, overflow labels, the whole catalogue. It handles positioning, sizing, color theming, dot mode, accessible markup, and even knows the difference between a circle and a rectangle.&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%2Fqfqp34vjjcwdd8132hhj.jpeg" 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%2Fqfqp34vjjcwdd8132hhj.jpeg" alt="one does not simply center a badge on a circular avatar" width="651" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've ever opened your browser devtools at 11pm trying to figure out why a badge is floating 4px off the corner of an avatar instead of sitting flush on the arc, Badge RS is the component you wish had existed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Anchor&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The positioning wrapper. Drop it around any element and it becomes a badge target. Uses &lt;code&gt;position: relative; display: inline-flex;&lt;/code&gt; so it doesn't break your layout, doesn't eat your accessibility tree, and doesn't require you to memorize any CSS tricks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;badges_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;badges_rs&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[function_component(NotificationBell)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;notification_bell&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="n"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Inbox, 5 unread messages"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"📬"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;
                &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5 unread messages"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="o"&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;That's it. The badge positions itself. You decide where.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Badge&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The actual indicator. Pass children and you get a labeled badge with text inside. Skip children and you get a compact do, no extra prop needed, just don't put anything inside.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A labeled count badge&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5 unread"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// A status dot, no children, no extra prop&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BottomRight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Online"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Same component, two modes. The dot is not a separate component.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;BadgeLabel&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A thin &lt;code&gt;&amp;lt;span class="badge__label"&amp;gt;&lt;/code&gt; wrapper. Used automatically when you pass plain text to &lt;code&gt;Badge&lt;/code&gt;. Expose it directly when you need extra CSS classes or styling on the label slot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Colors, Variants, Sizes
&lt;/h2&gt;

&lt;p&gt;The full set of knobs is available:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Colors&lt;/span&gt;
&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;

&lt;span class="c1"&gt;// Variants (three visual styles)&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Primary&lt;/span&gt;    &lt;span class="c1"&gt;// solid fill&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Secondary&lt;/span&gt;  &lt;span class="c1"&gt;// outlined&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Soft&lt;/span&gt;       &lt;span class="c1"&gt;// muted, lower-contrast&lt;/span&gt;

&lt;span class="c1"&gt;// Sizes&lt;/span&gt;
&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sm&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Md&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Lg&lt;/span&gt;

&lt;span class="c1"&gt;// Placement&lt;/span&gt;
&lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TopRight&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TopLeft&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BottomRight&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BottomLeft&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;All combinations work. TopLeft is there for RTL layouts and anyone who likes to be contrarian about badge placement.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Positioning Bug Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Here's the subtle one. &lt;code&gt;top: 0; right: 0&lt;/code&gt; with &lt;code&gt;transform: translate(50%, -50%)&lt;/code&gt; centers a badge perfectly on the corner of a &lt;strong&gt;rectangle&lt;/strong&gt;. That's fine for icon buttons, list items, or anything with a square bounding box.&lt;/p&gt;

&lt;p&gt;For a &lt;strong&gt;circle&lt;/strong&gt;, which is what every avatar in existence is, the story is different. A circle's actual edge at 45° sits inward from the bounding box corner. The geometric offset is exactly &lt;code&gt;1 - sin(45°)&lt;/code&gt;, which works out to roughly &lt;strong&gt;14.64%&lt;/strong&gt; of the element's width and height.&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%2F9u5nnmj96400cbtbwqwn.jpeg" 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%2F9u5nnmj96400cbtbwqwn.jpeg" alt="math lady" width="681" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most badge implementations ignore this. The badge floats slightly off the arc, nobody files a bug, and the designer quietly seethes.&lt;/p&gt;

&lt;p&gt;Badge RS exposes a &lt;code&gt;Shape&lt;/code&gt; enum to handle this explicitly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// top: 0; right: 0, standard bounding box corner&lt;/span&gt;
    &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// top: 14.64%; right: 14.64%, sits on the arc&lt;/span&gt;
&lt;span class="p"&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 rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// On a circular avatar, badge sits flush on the arc:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// On a square icon button, badge sits on the bounding box corner:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"New"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"New"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The math is not magic. It's just trigonometry that nobody wanted to look up at 11pm. We looked it up for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  Framework Parity
&lt;/h2&gt;

&lt;p&gt;All three frameworks ship the same API surface:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Yew&lt;/th&gt;
&lt;th&gt;Dioxus&lt;/th&gt;
&lt;th&gt;Leptos&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Anchor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Badge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BadgeLabel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Shape::Circle&lt;/code&gt; offset&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dot mode (no children)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All placements&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All variants&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARIA attributes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you've used it in Yew, you already know how to use it in Dioxus and Leptos. The prop names don't even change.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessibility
&lt;/h2&gt;

&lt;p&gt;Accessible badges are an afterthought in most libraries. In Badge RS they're mandatory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Badge&lt;/code&gt; renders with &lt;code&gt;role="status"&lt;/code&gt; and a required &lt;code&gt;aria_label&lt;/code&gt;. Screen readers announce the content without the user having to navigate to it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aria-atomic="true"&lt;/code&gt; ensures the full label is re-read when the count updates. A badge that goes from "3" to "4" reads "4 unread messages", not just "4".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Anchor&lt;/code&gt; renders as a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; with no ARIA role, because it's structural glue and should be invisible to assistive technology.&lt;/li&gt;
&lt;li&gt;The WCAG guidance on badges is straightforward: &lt;strong&gt;label the element that owns the badge, not just the badge itself&lt;/strong&gt;. We mention this in the docs and the examples follow it throughout.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The accessible way, the host element's label includes the count&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt; &lt;span class="n"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Inbox, 5 unread messages"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"📬"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5 unread messages"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The badge label and the host's aria-label should tell the same story from different angles.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Yew&lt;/span&gt;
cargo add badges-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add badges-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add badges-rs &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No CSS framework required. Styles are computed inline from the prop values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dot Mode vs Count Mode
&lt;/h2&gt;

&lt;p&gt;One component, two modes, no separate component for each. This matters because it keeps your import surface small and your mental model consistent.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Count mode, children present&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"5 messages"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Dot mode, no children, badge renders as a small filled circle&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BottomRight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Online"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The dot is a first-class mode with its own size calculations. &lt;code&gt;Size::Sm&lt;/code&gt; in dot mode renders a 6×6px dot. In count mode, it renders a 16×16px pill. The size label refers to the visual weight, not a fixed pixel value.&lt;/p&gt;
&lt;h2&gt;
  
  
  Status Indicators
&lt;/h2&gt;

&lt;p&gt;The placement prop combined with dot mode covers the most common avatar status pattern:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;badges_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;leptos&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;badges_rs&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;leptos&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[component]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;UserAvatar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IntoView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;view!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;
                &lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/* your avatar CSS */"&lt;/span&gt;
                &lt;span class="n"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Jane Doe, online"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;"JD"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Badge&lt;/span&gt;
                &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt;
                &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nn"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;
                &lt;span class="n"&gt;placement&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nn"&gt;Placement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BottomRight&lt;/span&gt;
                &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Online"&lt;/span&gt;
            &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="o"&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;Green dot, bottom-right, perfectly on the arc. That's the whole pattern.&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%2Fxjso8jyvkbxme41vjc0n.jpeg" 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%2Fxjso8jyvkbxme41vjc0n.jpeg" alt="it works, deploy it" width="447" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What We Didn't Do
&lt;/h2&gt;

&lt;p&gt;No magic threshold that auto-truncates to "99+". That's application logic, not component logic. We show whatever you pass in. If you want &lt;code&gt;count.min(99).to_string()&lt;/code&gt; or &lt;code&gt;"99+"&lt;/code&gt;, that's two lines in your own code.&lt;/p&gt;

&lt;p&gt;No auto-detection of the parent element's shape. That would require measuring the DOM at runtime, which is expensive. Instead: explicit &lt;code&gt;shape&lt;/code&gt; prop. You know your own design system. Tell us.&lt;/p&gt;

&lt;p&gt;No CSS injection. No global stylesheet to import. No BEM class naming conventions to memorize. The styles live on the element.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Badge RS&lt;/strong&gt; is compact by design. Three components, one enum, one positioning decision that most libraries get wrong.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Shape&lt;/code&gt; prop is the detail worth remembering. If you're putting badges on circular avatars and they look slightly off, that's the fix. Try &lt;code&gt;Shape::Circle&lt;/code&gt; and stop adjusting pixel offsets in your component stylesheets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://badges-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out" width="215" height="66"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/badges-rs" rel="noopener noreferrer"&gt;
        badges-rs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🏷️ A highly customizable badge component for WASM frameworks.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🏷️ Badges RS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/badges-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5e2f7d8b4cee002d878621939ed713f3232ef4489b55a84b96a3f4912e20847d/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f6261646765732d7273" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/badges-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2bece83e83e1570bf59f69764afed53a9b45a04640519f7f47f90994ae34b1d2/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f6261646765732d7273" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a9cc2654773e402fc68cb216f1e855aee03925e8d599a60a9118ec7ded24a306/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f6261646765732d7273"&gt;&lt;img src="https://camo.githubusercontent.com/a9cc2654773e402fc68cb216f1e855aee03925e8d599a60a9118ec7ded24a306/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f6261646765732d7273" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/31c82dd347f4da3b0ee4fb00bdbab1450d962c202a7f1d46feeb52cb06c634fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e38392532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/badges-rs/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Fbadges-rs%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://badges-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://badges-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://badges-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible badge component for WASM frameworks: Yew, Dioxus, and Leptos.
Supports notification counts, status dots, labels, multiple colors, variants, sizes, and placements
with full WCAG compliance.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why Badges RS?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control color, variant, size, placement, class, style, and ARIA labels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🔴 Dot Mode&lt;/strong&gt;: When no children are provided the badge renders as a compact status dot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📍 Smart Placement&lt;/strong&gt;: Four corner placements (&lt;code&gt;top-right&lt;/code&gt;, &lt;code&gt;top-left&lt;/code&gt;, &lt;code&gt;bottom-right&lt;/code&gt;, &lt;code&gt;bottom-left&lt;/code&gt;) via CSS &lt;code&gt;transform&lt;/code&gt; for pixel-perfect positioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;♿ Accessible by Default&lt;/strong&gt;: &lt;code&gt;role="status"&lt;/code&gt;, &lt;code&gt;aria-label&lt;/code&gt;, and &lt;code&gt;aria-atomic&lt;/code&gt; wired up automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧩 Framework Agnostic&lt;/strong&gt;: Same API semantics across Yew, Dioxus, and Leptos.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Y Yew Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/badges-rs/blob/main/YEW.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Yew app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🧬 Dioxus Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/badges-rs/blob/main/DIOXUS.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/badges-rs" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>rust</category>
      <category>css</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🪪 Avatar RS: Very Efficient Avatar Components for WASM Frameworks</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 27 Sep 2026 11:01:40 +0000</pubDate>
      <link>https://dev.to/wiseai/avatar-rs-very-efficient-avatar-components-for-wasm-frameworks-3lkn</link>
      <guid>https://dev.to/wiseai/avatar-rs-very-efficient-avatar-components-for-wasm-frameworks-3lkn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Bien le bonjour 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every WASM app eventually needs an avatar. Profile pictures, user cards, comment threads, they're everywhere. And every time, developers end up rolling the same &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag with some fallback logic, hardcoded border-radius, and a prayer that the CDN doesn't return a 404.&lt;/p&gt;

&lt;p&gt;That stops today. We're shipping &lt;a href="https://github.com/opensass/avatar" rel="noopener noreferrer"&gt;&lt;strong&gt;Avatar RS&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Avatar RS?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Avatar RS&lt;/strong&gt; is a fully-featured avatar component for &lt;strong&gt;Yew&lt;/strong&gt;, &lt;strong&gt;Dioxus&lt;/strong&gt;, and &lt;strong&gt;Leptos&lt;/strong&gt;. It handles image loading, fallback text/icons, overflow groups, color themes, size variants, accessible markup, the whole thing. Built on top of &lt;a href="https://github.com/opensass/image-rs" rel="noopener noreferrer"&gt;&lt;strong&gt;Image RS&lt;/strong&gt;&lt;/a&gt;, which means you get smart lazy loading, blur-up placeholders, and responsive layouts for free.&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%2Fw6aanc5ty0p9osk1356c.jpeg" 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%2Fw6aanc5ty0p9osk1356c.jpeg" alt="one does not simply roll their own avatar component" width="651" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of it as the avatar component you'd build if you had infinite time and zero deadlines. We had neither, but here we are anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack Under the Hood
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Avatar RS&lt;/strong&gt; wraps &lt;strong&gt;Image RS&lt;/strong&gt;, our WASM-native image primitive, for the actual &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element. This is not a trivial detail.&lt;/p&gt;

&lt;p&gt;Image RS uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;Intersection Observer API&lt;/a&gt; for lazy loading, supports &lt;code&gt;srcset&lt;/code&gt;/&lt;code&gt;sizes&lt;/code&gt; for responsive images, and fires clean &lt;code&gt;on_load&lt;/code&gt; / &lt;code&gt;on_error&lt;/code&gt; callbacks. All of that comes for free inside every &lt;code&gt;Image&lt;/code&gt; you render. The avatar layer only adds &lt;strong&gt;context management&lt;/strong&gt; and &lt;strong&gt;state coordination&lt;/strong&gt; on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Avatar&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The container. Wraps &lt;code&gt;Image&lt;/code&gt; and &lt;code&gt;Fallback&lt;/code&gt;, provides the shared loading context, and inherits size/color/variant from a surrounding &lt;code&gt;Group&lt;/code&gt; if present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[function_component(MyProfile)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;my_profile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Ferris Prophet"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;
                &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://i.pravatar.cc/300"&lt;/span&gt;
                &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Ferris Prophet"&lt;/span&gt;
            &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&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="s"&gt;"JD"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="o"&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 fallback shows while the image loads, hides once it lands.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Fallback&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Text initials, an icon, or anything you want rendered when the image hasn't loaded yet (or doesn't exist at all). Supports a &lt;code&gt;delay_ms&lt;/code&gt; prop to intentionally delay reveal, useful when your image usually loads fast and you don't want the fallback to flash briefly then disappear.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fallback shows immediately:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&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="s"&gt;"MH"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Fallback waits 200ms before appearing (prevents flicker on fast connections):&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;delay_ms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&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="s"&gt;"JD"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Small prop, big UX difference.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Group&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Stack multiple avatars with automatic overlap, configurable max count, and an overflow badge showing how many more there are.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="nd"&gt;#[function_component(TeamStack)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;team_stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Lg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Project team"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://i.pravatar.cc/150?u=m1"&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 1"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&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="s"&gt;"M1"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 2"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://i.pravatar.cc/150?u=m2"&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 2"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&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="s"&gt;"M2"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt; &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 3"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://i.pravatar.cc/150?u=m3"&lt;/span&gt; &lt;span class="n"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Member 3"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Warning&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="s"&gt;"M3"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Fallback&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Avatar&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;
                &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
                &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Soft&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
                &lt;span class="n"&gt;aria_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3 more members"&lt;/span&gt;
            &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&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;Pass &lt;code&gt;max={Some(3)}&lt;/code&gt; and &lt;code&gt;total={Some(6)}&lt;/code&gt;, and &lt;code&gt;Count&lt;/code&gt; automatically shows &lt;code&gt;+3&lt;/code&gt;. The math is done for you. The CSS overlap is done for you. You just write components.&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%2Fktuzlbhytd3023ywcg7d.jpeg" 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%2Fktuzlbhytd3023ywcg7d.jpeg" alt="math lady" width="681" height="445"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The &lt;code&gt;overflow_count&lt;/code&gt; Context
&lt;/h2&gt;

&lt;p&gt;This is the part that required actual thought.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Group&lt;/code&gt; computes &lt;code&gt;overflow_count = total - max&lt;/code&gt; and pushes it into context. &lt;code&gt;Count&lt;/code&gt; reads it from context when its own &lt;code&gt;count&lt;/code&gt; prop is zero (the default). This means the badge doesn't need to know anything explicit, it just reads the group state.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In Group:&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;overflow_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="nf"&gt;.saturating_sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;ctx_provider&lt;/span&gt;&lt;span class="nf"&gt;.provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;GroupContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;overflow_count&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="c1"&gt;// In Count:&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;effective_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ctx_overflow&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Renders: "+{effective_count}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One source of truth.&lt;/p&gt;
&lt;h2&gt;
  
  
  Framework Parity
&lt;/h2&gt;

&lt;p&gt;All three frameworks ship the same API surface:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Yew&lt;/th&gt;
&lt;th&gt;Dioxus&lt;/th&gt;
&lt;th&gt;Leptos&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Avatar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Image&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Fallback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Group&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;total&lt;/code&gt; + &lt;code&gt;max&lt;/code&gt; overflow&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context propagation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;delay_ms&lt;/code&gt; on fallback&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image RS integration&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Dioxus and Leptos implementation uses &lt;code&gt;use_context_provider&lt;/code&gt; / &lt;code&gt;use_context&lt;/code&gt; idioms native to each framework, but the behavior is identical. If you've used it in Yew, you already know how to use it in Leptos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Soft Refresh &amp;amp; The Browser Cache Fix
&lt;/h2&gt;

&lt;p&gt;Here's one that caught us off guard. In Yew, images rendered via &lt;code&gt;Image&lt;/code&gt; would sometimes fail to appear after a soft page refresh. Hard refresh? Fine. Soft? Gone.&lt;/p&gt;

&lt;p&gt;The culprit: when a browser serves an image from cache, the &lt;code&gt;load&lt;/code&gt; event fires &lt;em&gt;before&lt;/em&gt; Yew has had a chance to attach the listener. The effect sees a "loading" state, the image is already done, and the component never flips to "loaded".&lt;/p&gt;

&lt;p&gt;The fix was straightforward once we knew what to look for. We inject a &lt;code&gt;node_ref&lt;/code&gt; into the underlying &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element and check &lt;code&gt;img.complete&lt;/code&gt; on mount:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;use_effect_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="py"&gt;.src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;already_loaded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node_ref&lt;/span&gt;
            &lt;span class="py"&gt;.cast&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;web_sys&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HtmlImageElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="nf"&gt;.complete&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;already_loaded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ImageLoadingStatus&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Loaded&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;ImageLoadingStatus&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Loading&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="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 required adding &lt;code&gt;web-sys&lt;/code&gt; with the &lt;code&gt;HtmlImageElement&lt;/code&gt; feature to the &lt;code&gt;yew&lt;/code&gt; feature gate in &lt;code&gt;Cargo.toml&lt;/code&gt;. A small addition, but it closes a genuinely annoying browser quirk.&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%2F4wnh8htpimmv6vyqvz8x.jpeg" 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%2F4wnh8htpimmv6vyqvz8x.jpeg" alt="it works on my machine" width="554" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dioxus and Leptos did not have this issue, their reactive systems handle DOM updates differently and don't suffer from this ordering problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Colors, Variants, Sizes
&lt;/h2&gt;

&lt;p&gt;Everything inherits downward through context. Set defaults at the group level, override them per-avatar if needed.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Colors&lt;/span&gt;
&lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Accent&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Danger&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Variants&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;  &lt;span class="c1"&gt;// solid fill&lt;/span&gt;
&lt;span class="nn"&gt;Variant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Soft&lt;/span&gt;     &lt;span class="c1"&gt;// muted, lower-contrast&lt;/span&gt;

&lt;span class="c1"&gt;// Sizes&lt;/span&gt;
&lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Xs&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sm&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Md&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Lg&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Xl&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Xxl&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Color::Custom("...")&lt;/code&gt; and &lt;code&gt;Size::Custom("...")&lt;/code&gt; accept raw CSS strings, so if your design system uses &lt;code&gt;hsl(270 60% 50%)&lt;/code&gt; or &lt;code&gt;3.5rem&lt;/code&gt;, those work too.&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Yew&lt;/span&gt;
cargo add avatar &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;yew

&lt;span class="c"&gt;# Dioxus&lt;/span&gt;
cargo add avatar &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dio

&lt;span class="c"&gt;# Leptos&lt;/span&gt;
cargo add avatar &lt;span class="nt"&gt;--features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. The styling is computed inline from the prop values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Accessibility
&lt;/h2&gt;

&lt;p&gt;Every component exposes its ARIA props explicitly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Avatar&lt;/code&gt; renders &lt;code&gt;role="img"&lt;/code&gt; with a required &lt;code&gt;aria_label&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Image&lt;/code&gt; manages &lt;code&gt;aria-hidden&lt;/code&gt; based on loading state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Fallback&lt;/code&gt; is hidden from assistive tech once the image loads.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Group&lt;/code&gt; gets an &lt;code&gt;aria_label&lt;/code&gt; for the whole group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Count&lt;/code&gt; gets its own &lt;code&gt;aria_label&lt;/code&gt; (defaults to &lt;code&gt;"Additional members"&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Screen readers get a consistent, clear picture regardless of whether images loaded or not.&lt;/p&gt;
&lt;h2&gt;
  
  
  What We Didn't Do
&lt;/h2&gt;

&lt;p&gt;No auto-injection of count badges. No magic child-slicing that differs between frameworks. No runtime diffing of the children list to figure out how many to show. These patterns break in different ways across Yew, Dioxus, and Leptos, and they make the component harder to reason about.&lt;/p&gt;

&lt;p&gt;Instead: &lt;strong&gt;explicit &lt;code&gt;total&lt;/code&gt; and &lt;code&gt;max&lt;/code&gt; props&lt;/strong&gt;, &lt;strong&gt;explicit &lt;code&gt;Count&lt;/code&gt; placement&lt;/strong&gt;, &lt;strong&gt;one context object&lt;/strong&gt; that everything reads from. It's a little more to type. It's a lot easier to debug.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Avatar RS&lt;/strong&gt; is exactly what it says on the tin: a production-ready avatar component for WASM apps.&lt;/p&gt;

&lt;p&gt;It's backed by Image RS, which means you get all the image loading sophistication without reinventing it. The overflow logic is explicit and predictable. Framework parity is real, not aspirational.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://avatar-rs.netlify.app" rel="noopener noreferrer"&gt;&lt;br&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%2Fqcspj4eqdqxf6dp022kl.png" alt="Try It Out" width="215" height="66"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.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.amazonaws.com%2Fuploads%2Farticles%2Fwl06pc60hq9ugm11p8vp.png" alt="Try It" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;
        opensass
      &lt;/a&gt; / &lt;a href="https://github.com/opensass/avatar" rel="noopener noreferrer"&gt;
        avatar
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      👦 A highly customizable avatar component for WASM frameworks (Powered by Image RS).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;👦 Avatar&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/avatar" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b957c3c6a2262900494b96f7916a83d6656f3919f2cf36b10633636335a44eee/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f617661746172" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://crates.io/crates/avatar" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6d1e440630631da77476b3de471b081414c7ae04ef3b3fc8171ed2d67f14e7f5/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f642f617661746172" alt="Crates.io Downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/10a004fc9a4e7b7c49f5eb1cf322f5834de29fe78588b6fd894bbfe8d80a12a7/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f617661746172"&gt;&lt;img src="https://camo.githubusercontent.com/10a004fc9a4e7b7c49f5eb1cf322f5834de29fe78588b6fd894bbfe8d80a12a7/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f6c2f617661746172" alt="Crates.io License"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/44b045d4da6c2fd8024c8c66a350a4c8bb9c17faf50009f34dbe64c530de2454/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d616465253230776974682d527573742d3166343235662e7376673f6c6f676f3d72757374266c6f676f436f6c6f723d7768697465" alt="made-with-rust"&gt;&lt;/a&gt;
&lt;a href="https://www.rust-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/31c82dd347f4da3b0ee4fb00bdbab1450d962c202a7f1d46feeb52cb06c634fb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f527573742d312e38392532422d626c75652e737667" alt="Rust"&gt;&lt;/a&gt;
&lt;a href="https://github.com/opensass" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5ca62441414bacaa54c6c6e5b68e46c76305947b6bf498c4949fc71c1b4b10dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61696e7461696e65642533462d7965732d677265656e2e737667" alt="Maintenance"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://discord.gg/b5JbvHW5nv" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1de0ff4ce5ecb14813fe0a4ae22bfb7ab081d2255bde28b216e2d3dc454524d9/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f62354a62764857356e76" alt="Open SASS Discord"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/opensass/avatar/refs/heads/main/assets/logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fopensass%2Favatar%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Demo&lt;/h2&gt;
&lt;/div&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;Live Demo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yew&lt;/td&gt;
&lt;td&gt;&lt;a href="https://avatar-rs.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dioxus&lt;/td&gt;
&lt;td&gt;&lt;a href="https://avatar-dio.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leptos&lt;/td&gt;
&lt;td&gt;&lt;a href="https://avatar-lep.netlify.app" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a2765425215b2af5774668447ff125324caed6bfe2bd4fc6ee74bbbe158c8046/68747470733a2f2f6170692e6e65746c6966792e636f6d2f6170692f76312f6261646765732f62323133313332612d643862362d343934622d386135662d3732393036383261316139352f6465706c6f792d737461747573" alt="Netlify Status"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📜 Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A highly customizable, accessible avatar component for WASM frameworks: Yew, Dioxus, and Leptos.
Supports image loading with automatic fallback content, multiple sizes, color themes, and full WCAG compliance.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 Why Avatar?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;🎨 Fully Customizable&lt;/strong&gt;: Control every attribute, class, style, size, color, variant, ARIA labels and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🖼️ Smart Image Loading&lt;/strong&gt;: Tracks &lt;code&gt;idle → loading → loaded/error&lt;/code&gt; status with context. Fallback is shown until the image is ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⏱ Delay Support&lt;/strong&gt;: Prevent flash-of-fallback on fast connections with &lt;code&gt;delay_ms&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;♿ Accessible by Default&lt;/strong&gt;: &lt;code&gt;role="img"&lt;/code&gt;, &lt;code&gt;aria-label&lt;/code&gt;, &lt;code&gt;aria-hidden&lt;/code&gt; wired up automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🧩 Framework Agnostic&lt;/strong&gt;: Same API semantics across Yew, Dioxus, and Leptos.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Y Yew Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/avatar/blob/main/YEW.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Yew app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🧬 Dioxus Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href="https://github.com/opensass/avatar/blob/main/DIOXUS.md" rel="noopener noreferrer"&gt;our guide&lt;/a&gt; to integrate this component into your Dioxus app.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌱 Leptos&lt;/h2&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/opensass/avatar" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We are Open SASS, babe!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're working tirelessly on making Rust web development extremely easy for everyone.&lt;/p&gt;

&lt;p&gt;If you made it this far, it would be nice if you could &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Till next time 👋!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>rust</category>
      <category>css</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Resurrected a Dead CRC Crate and It Suddenly Went Viral</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 20 Sep 2026 09:11:49 +0000</pubDate>
      <link>https://dev.to/wiseai/i-resurrected-a-dead-crc-crate-and-it-suddenly-went-viral-3894</link>
      <guid>https://dev.to/wiseai/i-resurrected-a-dead-crc-crate-and-it-suddenly-went-viral-3894</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Bonjour 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there I was, browsing &lt;a href="https://crates.io" rel="noopener noreferrer"&gt;crates.io&lt;/a&gt; at an hour that most reasonable people would describe as "the middle of the night", doing what all emotionally stable developers do at that hour: auditing dead Rust crates for signs of life.&lt;/p&gt;

&lt;p&gt;That's when I found &lt;a href="https://crates.io/crates/crc32" rel="noopener noreferrer"&gt;&lt;code&gt;crc32&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not &lt;code&gt;crc32fast&lt;/code&gt;. Not &lt;code&gt;crc&lt;/code&gt;. Not &lt;code&gt;crc32c&lt;/code&gt;. The original. The stubby, ancient, &lt;code&gt;crc32&lt;/code&gt; crate. Last published in 2015. No changelog. No CI. A &lt;code&gt;Cargo.toml&lt;/code&gt; that predates most of the stable Rust syntax I use daily. And sitting there, abandoned and unloved.&lt;/p&gt;

&lt;p&gt;People were using this thing. Were probably &lt;em&gt;shipping&lt;/em&gt; software with it in their dependency tree. They just didn't know how to reach the crate maintainer, who had apparently retired to a cabin in the woods with no internet access sometime around when Rust 1.0 was announced.&lt;/p&gt;

&lt;p&gt;I stared at those download numbers for thirty seconds.&lt;/p&gt;

&lt;p&gt;Then I did what any emotionally stable rustacean would do: I resurrected it. From the ashes. In modern Rust. With &lt;code&gt;no_std&lt;/code&gt;. With Python bindings. With a build-time proc-macro codegen crate. With CI/CD, Debian packaging, RPM packaging, and a Ferris logo.&lt;/p&gt;

&lt;p&gt;You know. Normal stuff.&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%2Fcuchucbp5f0jlwsuzmzm.jpeg" 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%2Fcuchucbp5f0jlwsuzmzm.jpeg" alt="shipping Ferris to production" width="717" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, What Even Is CRC-32?
&lt;/h2&gt;

&lt;p&gt;CRC-32 stands for Cyclic Redundancy Check, 32-bit variant. It's the checksum algorithm that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ZIP files&lt;/strong&gt; use to verify archive integrity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ethernet frames&lt;/strong&gt; use to detect bit errors in transmission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FDDI, PKZIP, PNG&lt;/strong&gt; and approximately half the binary protocols ever invented also use.&lt;/li&gt;
&lt;li&gt;Every &lt;code&gt;zlib&lt;/code&gt; function you've ever called calls internally when you weren't paying attention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, CRC-32 is &lt;em&gt;everywhere&lt;/em&gt;. It's the duct tape of data integrity. It's been computing checksums since before most of today's developers were handing in their first homework assignments.&lt;/p&gt;

&lt;p&gt;The original Rust &lt;code&gt;crc32&lt;/code&gt; crate implemented the byte-at-a-time version, the classic, the grandaddy variant. Simple. Correct. Slow as a 56k modem by 2024 standards.&lt;/p&gt;

&lt;p&gt;I didn't just port it. I rewrote the whole thing from the zlib source, added slicing-by-4, slicing-by-8, and slicing-by-16 table variants, pulled the table-generation itself into a build-time proc-macro subcrate, added a streaming &lt;code&gt;Digest&lt;/code&gt;, a GF(2) matrix &lt;code&gt;combine&lt;/code&gt; function, and shipped the whole thing as a &lt;code&gt;no_std&lt;/code&gt; library with Python and Node.js bindings.&lt;/p&gt;

&lt;p&gt;All in 100% safe Rust. With &lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; at the crate root.&lt;/p&gt;

&lt;p&gt;Because anything worth resurrecting is worth resurrecting &lt;em&gt;properly&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Let me tell you what the original &lt;code&gt;crc32&lt;/code&gt; crate looked like. It was, essentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/lib.rs
src/crc32gen.rs
src/crc32gen_file.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. 3 files. A lookup table, a loop, a bitwise XOR. Beautiful in its simplicity, like a stone hut in a field. Functional. Zero frills. Absolutely not capable of 1 GiB/s throughput.&lt;/p&gt;

&lt;p&gt;Here's what &lt;code&gt;crc32-v2&lt;/code&gt; looks like today:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crc32-v2/
├── crc32-codegen/             ← proc-macro subcrate: generates all 17 CRC tables at build time
│   └── src/lib.rs             ← build.rs calls crc32_codegen::run() → writes to $OUT_DIR
├── src/
│   ├── lib.rs                 ← minimal entry point: #![no_std], module declarations, Python FFI
│   ├── tables.rs              ← crc32() byte-at-a-time baseline
│   ├── byfour.rs              ← crc32_little / _8 / _16 / crc32_big
│   ├── combine.rs             ← crc32_combine() via GF(2) matrix squaring in O(log n)
│   ├── digest.rs              ← streaming Digest with update() / finalize() / digest()
│   └── python.rs              ← PyO3 bindings (gated on feature = "python" + "std")
├── tests/
│   └── byfour.rs              ← 40 Rust integration tests
└── python/
    └── crc32_rs/
        └── __init__.py        ← re-exports all symbols from the compiled .so
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The stone hut has been converted into a, uh, &lt;em&gt;well-appointed facility&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy8enypsfoj2eywwf3hry.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy8enypsfoj2eywwf3hry.webp" alt="Before and after the refactor" width="640" height="640"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Magic Trick
&lt;/h2&gt;

&lt;p&gt;This is my personal favourite part of the whole project. And possibly the most unhinged.&lt;/p&gt;

&lt;p&gt;CRC-32 slicing-by-16 requires 17 lookup tables: one 256-entry big-endian table, and 16 256-entry little-endian tables at different offsets. That's 17 × 256 × 4 = 17,408 bytes of lookup table data that needs to exist at runtime.&lt;/p&gt;

&lt;p&gt;The naive way: write the tables by hand and commit 17,000 bytes of constants to git as a &lt;code&gt;.rs&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The normal way: generate them at startup and cache them in a &lt;code&gt;static&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The way I did it: proc-macro subcrate (&lt;code&gt;crc32-codegen&lt;/code&gt;) that is invoked from &lt;code&gt;build.rs&lt;/code&gt; at compile time, generates all 17 tables using the CRC-32 polynomial arithmetic, writes them to &lt;code&gt;$OUT_DIR/crc_tables.rs&lt;/code&gt;, and the main crate &lt;code&gt;include!&lt;/code&gt;s the output. Zero runtime initialization. Zero startup cost. The tables are baked into the binary at link time.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build-dependencies]&lt;/span&gt;
&lt;span class="py"&gt;crc32-codegen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"crc32-codegen"&lt;/span&gt; &lt;span class="p"&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 rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;crc32_codegen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&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;That's the entire &lt;code&gt;build.rs&lt;/code&gt;. One function call. The codegen crate does all the polynomial math, formats the Rust source, and writes it to disk. The main crate wakes up with all 17 tables pre-computed, pre-verified, and pre-formatted.&lt;/p&gt;

&lt;p&gt;This is the kind of thing that inspires either awe or a mildly concerned Slack message from your coworkers. There is no middle ground.&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%2F15bfp2ywzsqzcge02ekx.jpeg" 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%2F15bfp2ywzsqzcge02ekx.jpeg" alt="Ferris generating a lookup table" width="500" height="701"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The 4 Speeds of CRC-32
&lt;/h2&gt;

&lt;p&gt;Let me paint you a picture of what "slicing-by-N" actually means, because it's one of those ideas that sounds arcane until you see the numbers and then you can't stop thinking about it.&lt;/p&gt;

&lt;p&gt;The classic CRC-32 loop looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CRC_TABLE&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="n"&gt;index&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;usize&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="n"&gt;crc&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&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 byte per iteration. One table lookup. On a 1 MiB payload that's 1,048,576 iterations. At ~2 ns per iteration (fast CPU, warm cache), that's ~2ms. Not terrible. Not great.&lt;/p&gt;

&lt;p&gt;Slicing-by-4 says: what if we process &lt;em&gt;four&lt;/em&gt; bytes per iteration instead? You pre-compute four separate 256-entry tables (one for each byte offset), and in each step you XOR together four table lookups instead of one. Four bytes per iteration, four table lookups, but modern CPUs can do all four lookups in parallel because there are no data dependencies between them. Result: roughly 2.4× faster.&lt;/p&gt;

&lt;p&gt;Slicing-by-8 does the same with eight tables. Slicing-by-16 pushes it to sixteen tables and sixteen bytes per step, letting the CPU's out-of-order execution and instruction-level parallelism do the heavy lifting. With &lt;code&gt;#[inline(always)]&lt;/code&gt; on the inner fold functions, fat LTO, and &lt;code&gt;overflow-checks = false&lt;/code&gt; in the bench profile, LLVM sees through all the abstraction and generates machine code that is, frankly, embarrassingly fast for code written entirely in safe Rust.&lt;/p&gt;

&lt;p&gt;The full breakdown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;1 B&lt;/th&gt;
&lt;th&gt;64 B&lt;/th&gt;
&lt;th&gt;1 KiB&lt;/th&gt;
&lt;th&gt;64 KiB&lt;/th&gt;
&lt;th&gt;1 MiB&lt;/th&gt;
&lt;th&gt;Throughput&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;crc32&lt;/code&gt; (byte-at-a-time)&lt;/td&gt;
&lt;td&gt;2 ns&lt;/td&gt;
&lt;td&gt;167 ns&lt;/td&gt;
&lt;td&gt;2,856 ns&lt;/td&gt;
&lt;td&gt;188,134 ns&lt;/td&gt;
&lt;td&gt;2,916,562 ns&lt;/td&gt;
&lt;td&gt;~343 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;crc32_little&lt;/code&gt; (slicing-by-4)&lt;/td&gt;
&lt;td&gt;3 ns&lt;/td&gt;
&lt;td&gt;73 ns&lt;/td&gt;
&lt;td&gt;1,086 ns&lt;/td&gt;
&lt;td&gt;82,129 ns&lt;/td&gt;
&lt;td&gt;1,199,953 ns&lt;/td&gt;
&lt;td&gt;~833 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;crc32_little_8&lt;/code&gt; (slicing-by-8)&lt;/td&gt;
&lt;td&gt;3 ns&lt;/td&gt;
&lt;td&gt;61 ns&lt;/td&gt;
&lt;td&gt;922 ns&lt;/td&gt;
&lt;td&gt;56,486 ns&lt;/td&gt;
&lt;td&gt;1,004,746 ns&lt;/td&gt;
&lt;td&gt;~1,004 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_little_16&lt;/code&gt; (slicing-by-16)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;39 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;753 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;48,101 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;781,535 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~1,282 MiB/s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;crc32fast&lt;/code&gt; (SIMD via &lt;code&gt;pclmulqdq&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;11 ns&lt;/td&gt;
&lt;td&gt;20 ns&lt;/td&gt;
&lt;td&gt;102 ns&lt;/td&gt;
&lt;td&gt;5,802 ns&lt;/td&gt;
&lt;td&gt;89,204 ns&lt;/td&gt;
&lt;td&gt;~11,300 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;crc32_little_16&lt;/code&gt; hits &lt;strong&gt;~1,282 MiB/s&lt;/strong&gt; on a 1 MiB payload. That's &lt;strong&gt;3.7× faster than the baseline&lt;/strong&gt;, without a single SIMD intrinsic, without a single &lt;code&gt;unsafe&lt;/code&gt; block, and without any CPU feature detection. It Just Works on x86-64, ARM, RISC-V, WASM, and whatever exotic architecture you're running this week.&lt;/p&gt;

&lt;p&gt;Note that tiny 1-byte payloads still favour the baseline &lt;code&gt;crc32&lt;/code&gt; (2 ns vs 3 ns) because the slicing variants pay a small alignment prologue overhead. We document this honestly, unlike some people's README files.&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%2Fdp631ld7sgjrs9h0lsmy.jpeg" 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%2Fdp631ld7sgjrs9h0lsmy.jpeg" alt="Surprised Ferris" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Cross-Library Reality Check
&lt;/h2&gt;

&lt;p&gt;Look. I know what you're thinking. &lt;em&gt;"But crc32fast uses SIMD and does 11 GiB/s. Doesn't that make this pointless?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No. Here's why.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;crc32fast&lt;/code&gt; is genuinely excellent for x86-64 with &lt;code&gt;pclmulqdq&lt;/code&gt;. But &lt;code&gt;crc32-v2&lt;/code&gt; occupies a different niche:&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;Method&lt;/th&gt;
&lt;th&gt;Time (1 MiB)&lt;/th&gt;
&lt;th&gt;Throughput&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crc32fast&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;89,204 ns&lt;/td&gt;
&lt;td&gt;~11,300 MiB/s&lt;/td&gt;
&lt;td&gt;SIMD (&lt;code&gt;pclmulqdq&lt;/code&gt;) / Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;zlib-rs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;crc32&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;96,968 ns&lt;/td&gt;
&lt;td&gt;~10,390 MiB/s&lt;/td&gt;
&lt;td&gt;SIMD / Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python (&lt;code&gt;zlib.crc32&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;C extension&lt;/td&gt;
&lt;td&gt;355,270 ns&lt;/td&gt;
&lt;td&gt;~2,815 MiB/s&lt;/td&gt;
&lt;td&gt;SIMD / C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32-v2&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;crc32_little_16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;781,535 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~1,282 MiB/s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Pure safe Rust&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python (&lt;code&gt;crcmod&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;C extension&lt;/td&gt;
&lt;td&gt;2,865,836 ns&lt;/td&gt;
&lt;td&gt;~349 MiB/s&lt;/td&gt;
&lt;td&gt;Non-SIMD / C&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;crc32fast&lt;/code&gt;: amazing. &lt;code&gt;zlib-rs&lt;/code&gt;: also amazing. Both use runtime SIMD dispatch and &lt;code&gt;unsafe&lt;/code&gt;. Both don't compile to WASM without special handling. Both don't work in &lt;code&gt;no_std&lt;/code&gt; environments without a careful dance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;crc32-v2&lt;/code&gt; compiles everywhere Rust compiles. Embedded RISC-V? Yes. &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt;? Yes. A microcontroller that needs to verify a firmware checksum before flashing? Yes. A kernel module? With &lt;code&gt;#![no_std]&lt;/code&gt; and a custom allocator? &lt;em&gt;Also&lt;/em&gt; yes.&lt;/p&gt;

&lt;p&gt;When you need 11 GiB/s you use &lt;code&gt;crc32fast&lt;/code&gt;. When you need something that works anywhere, has zero dependencies outside &lt;code&gt;alloc&lt;/code&gt;, and is produced by a compiler that will literally refuse to let you write unsafe code: you use &lt;code&gt;crc32-v2&lt;/code&gt;. There are more situations in the second category than you'd expect.&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%2Fxwha4p4ia0681mhrdvpw.jpeg" 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%2Fxwha4p4ia0681mhrdvpw.jpeg" alt="use crc32-v2 davai davai" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Python Bindings
&lt;/h2&gt;

&lt;p&gt;Here's a section I am writing in the spirit of radical honesty. Shipping Python bindings for a Rust library requires configuring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maturin&lt;/code&gt; (the build tool)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pyo3&lt;/code&gt; (the FFI framework)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pyproject.toml&lt;/code&gt; (the Python packaging config)&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;python/crc32_rs/__init__.py&lt;/code&gt; that re-exports from the compiled &lt;code&gt;.so&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;module-name&lt;/code&gt; field in &lt;code&gt;pyproject.toml&lt;/code&gt; matching the &lt;code&gt;#[pymodule]&lt;/code&gt; name in Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any one of these four things is even slightly wrong, Python greets you with:&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="nb"&gt;ModuleNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;named&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;crc32_rs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Not a helpful error. Not &lt;code&gt;"the module-name in pyproject.toml doesn't match the pymodule attribute"&lt;/code&gt;. Just: it doesn't exist. Good luck.&lt;/p&gt;

&lt;p&gt;I went through approximately four rounds of this before getting it right. The root cause was a mismatch between &lt;code&gt;module-name = "crc32_v2._crc32_v2"&lt;/code&gt; (incorrect) and &lt;code&gt;module-name = "crc32_rs._crc32_v2"&lt;/code&gt; (correct). One underscore in the wrong namespace and Python acts as if the entire compiled extension simply does not exist in this universe.&lt;/p&gt;

&lt;p&gt;The fix took three characters. The investigation took forty-five minutes.&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crc32_rs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_little_16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_hex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Digest&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="mh"&gt;0xebe6c6e6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32_little_16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="mh"&gt;0xebe6c6e6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;ebe6c6e6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32_hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;ebe6c6e6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&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="sa"&gt;b&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&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="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;world!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalize&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;span class="mh"&gt;0xebe6c6e6&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nc"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0xEBE6C6E6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now it works. The Python interpreter is stuffed. We do not speak of the forty-five minutes.&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%2Fyvp98fw6ep6mnhfcb1nb.jpeg" 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%2Fyvp98fw6ep6mnhfcb1nb.jpeg" alt="same same" width="500" height="559"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Rust for Python Developers
&lt;/h2&gt;

&lt;p&gt;Let's talk about something that the throughput benchmarks don't fully capture: what happens to performance when you're computing CRC-32 on &lt;em&gt;tiny&lt;/em&gt; payloads? Like, really tiny. 1 byte tiny.&lt;/p&gt;

&lt;p&gt;The issue with Python's &lt;a href="https://docs.python.org/3/library/zlib.html#zlib.crc32" rel="noopener noreferrer"&gt;&lt;code&gt;zlib.crc32&lt;/code&gt;&lt;/a&gt; is not that it's slow for large inputs, it delegates to SIMD C code under the hood and handles 1 MiB payloads at 2,815 MiB/s, which is genuinely fast. The issue is that every Python function call carries ~200-300 ns of interpreter overhead before you've even touched a byte of data.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Payload&lt;/th&gt;
&lt;th&gt;Python &lt;code&gt;zlib.crc32&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Rust &lt;code&gt;crc32-v2&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 B&lt;/td&gt;
&lt;td&gt;~297 ns&lt;/td&gt;
&lt;td&gt;~2 ns&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~148×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64 B&lt;/td&gt;
&lt;td&gt;~301 ns&lt;/td&gt;
&lt;td&gt;~39 ns&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~7.7×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;148 times faster on a single byte. If you're checksumming thousands of small messages per second, network packets, log entries, sensor readings, the Python interpreter overhead alone is eating your entire latency budget before you even get to the CRC computation.&lt;/p&gt;

&lt;p&gt;Moving the loop into Rust and calling Python once at the end is not premature optimisation. It is the correct architectural decision. &lt;code&gt;crc32-v2&lt;/code&gt; makes that decision easier to implement.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;no_std&lt;/code&gt;: Ferris Goes Embedded
&lt;/h2&gt;

&lt;p&gt;This was the part I underestimated most. Adding &lt;code&gt;no_std&lt;/code&gt; support sounds simple: slap &lt;code&gt;#![cfg_attr(not(feature = "std"), no_std)]&lt;/code&gt; on the library, add &lt;code&gt;extern crate alloc&lt;/code&gt;, and done.&lt;/p&gt;

&lt;p&gt;And then you build the &lt;code&gt;cdylib&lt;/code&gt; target without &lt;code&gt;std&lt;/code&gt; features and discover that a dynamic library needs a panic handler and a global allocator, because without &lt;code&gt;std&lt;/code&gt;, the linker has no idea what to do when you panic, and with no allocator it has equally no idea what to do when something tries to allocate.&lt;/p&gt;

&lt;p&gt;The fix requires a dummy allocator implemention that satisfies the &lt;code&gt;GlobalAlloc&lt;/code&gt; trait contract just enough to let the linker stop complaining:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Features that gate the standard library&lt;/span&gt;
&lt;span class="nn"&gt;[features]&lt;/span&gt;
&lt;span class="py"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;std&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"pyo3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c"&gt;# Python bindings require std&lt;/span&gt;
&lt;span class="py"&gt;node&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"napi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"napi-derive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"napi-build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c"&gt;# Node.js too&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![cfg_attr(not(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="nd"&gt;),&lt;/span&gt; &lt;span class="nd"&gt;no_std)]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And &lt;code&gt;panic = "abort"&lt;/code&gt; in &lt;code&gt;[profile.dev]&lt;/code&gt; so that the &lt;code&gt;no_std&lt;/code&gt; cdylib doesn't try to set up unwinding infrastructure that doesn't exist.&lt;/p&gt;

&lt;p&gt;Result: &lt;code&gt;cargo build --no-default-features&lt;/code&gt; completes successfully. Ferris is now embeddable. The microcontroller community rejoices.&lt;/p&gt;
&lt;h2&gt;
  
  
  Safety
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; is enforced at the crate root. This is a compiler directive that physically prevents any &lt;code&gt;unsafe&lt;/code&gt; block from being compiled into the library.&lt;/p&gt;

&lt;p&gt;The borrow checker, like a very particular building inspector, will reject your PR on first principles if you try to introduce &lt;code&gt;unsafe&lt;/code&gt; into the slicing loops, the GF(2) matrix arithmetic, the streaming &lt;code&gt;Digest&lt;/code&gt;, or the codegen subcrate. You can argue with it. You can find workarounds. The borrow checker does not care. It has seen your workarounds and it finds them unconvincing.&lt;/p&gt;

&lt;p&gt;The only &lt;code&gt;unsafe&lt;/code&gt; surface is the Python FFI layer's dummy allocator stub needed for bare-metal builds, and this is isolated, cfg-gated, and documented. The rest of the crate is provably safe at compile time.&lt;/p&gt;

&lt;p&gt;This means you can use &lt;code&gt;crc32-v2&lt;/code&gt; in environments where one &lt;code&gt;unsafe&lt;/code&gt; bug could corrupt a firmware image, crash a file server, or cause a network device to accept invalid data. The compiler provides the guarantee. Not the tests. Not the code review. The &lt;em&gt;compiler&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Rust
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;crc32-v2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;

&lt;span class="c"&gt;# For embedded / no_std:&lt;/span&gt;
&lt;span class="c"&gt;# crc32-v2 = { version = "0.2.0", default-features = false }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crc32_v2&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_combine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;byfour&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;crc32_little_16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// One-shot&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32&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="s"&gt;b"123456789"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0xCBF43926&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Fastest pure-software path (~1,282 MiB/s)&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32_little_16&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="s"&gt;b"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0xEBE6_C6E6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Streaming&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"Hello, "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="nf"&gt;.finalize&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;0xEBE6_C6E6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Combine two independently-computed CRCs (O(log n) via GF(2) matrix squaring)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;crc32&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="s"&gt;b"Hello, "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;crc32&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="s"&gt;b"world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32_combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;crc32&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="s"&gt;b"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;crc32-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crc32_rs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_little_16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crc32_hex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Digest&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123456789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0xcbf43926&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# The correct CRC-32 of "rust_magic" is:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rust_magic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="mh"&gt;0xa3067d13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Node.js
&lt;/h3&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;crc32-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;crc32Little16&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crc32-rs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crc32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// ebe6c6e6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;The crate is at &lt;code&gt;0.2.0&lt;/code&gt; and functionally complete for its initial scope. The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slicing-by-32&lt;/strong&gt;: Because if 16 tables give us 3.7× speedup, we're obligated to find out where the speedup curve flattens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;serde&lt;/code&gt; support&lt;/strong&gt;: Serialize and deserialize &lt;code&gt;Digest&lt;/code&gt; state for resumable streaming checksums.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WASM target&lt;/strong&gt;: The &lt;code&gt;no_std&lt;/code&gt; foundation is already there. The WASM build should be trivial in theory. "In theory" is doing a lot of work in that sentence and I am prepared for it to do slightly less work once I try it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;crc32-v2&lt;/code&gt; started as a resurrection project. Someone wrote &lt;code&gt;crc32&lt;/code&gt; in 2015, abandoned it, and 9,062 people quietly became dependent on it through their transitive dependency graphs without knowing they were relying on a crate that predated Rust 1.0.&lt;/p&gt;

&lt;p&gt;It ended up as something that resurrected the algorithm &lt;em&gt;and&lt;/em&gt; pushed it forward: slicing-by-16 giving 3.7× throughput improvement, build-time table codegen via proc-macro, &lt;code&gt;no_std&lt;/code&gt; compatibility, Python and Node.js bindings, and Ferris the Crab holding a magic wand computing &lt;code&gt;0xa3067d13&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;The original &lt;code&gt;crc32&lt;/code&gt; crate was doing its best with 2015-era Rust. We can do more. We should do more. The 9,062 people who downloaded it deserve more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;cargo add crc32-v2&lt;/code&gt; → compute checksums → sleep well knowing Ferris has you covered 🦀⚡&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Star &lt;a href="https://github.com/wiseaidev/crc32-v2" rel="noopener noreferrer"&gt;the repo&lt;/a&gt;, try the &lt;a href="https://pypi.org/project/crc32-rs" rel="noopener noreferrer"&gt;Python bindings&lt;/a&gt;, install the &lt;a href="https://www.npmjs.com/package/crc32-rs" rel="noopener noreferrer"&gt;npm package&lt;/a&gt;, or read the &lt;a href="https://docs.rs/crc32-v2" rel="noopener noreferrer"&gt;docs&lt;/a&gt; if you still have questions.&lt;/p&gt;

&lt;p&gt;This has been a public service announcement from someone who looked at a dead Rust crate with 9,062 downloads and thought: &lt;em&gt;"Someone should fix this."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That someone was me. And honestly? It was a great use of my 2AM.&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%2F2o84fzwlmkt3mn078p00.jpg" 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%2F2o84fzwlmkt3mn078p00.jpg" alt="same same" width="500" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Till next time: &lt;em&gt;Keep the bytes honest. Keep the checksums rolling.&lt;/em&gt; 🦀🔄&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/wiseaidev" rel="noopener noreferrer"&gt;
        wiseaidev
      &lt;/a&gt; / &lt;a href="https://github.com/wiseaidev/crc32-v2" rel="noopener noreferrer"&gt;
        crc32-v2
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The fastest port of the CRC-32 algorithm in Rust.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⚡ CRC32-V2&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/wiseaidev/crc32-v2" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fcrc32-v2%2Frefs%2Fheads%2Fmain%2Fassets%2Fnew-logo.png" alt="CRC32-V2 Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/crc32-v2" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/52342ac216459f90eb3be6e9e10d401741e541adfccb939b0f0ac208d1b9de14/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f63726333322d76322e737667" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://docs.rs/crc32-v2" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/aea0ecbacc9e0a7050f8e74a214d87a9aa5bd519b76784d83dd2a1a7895534e5/68747470733a2f2f646f63732e72732f63726333322d76322f62616467652e737667" alt="Docs.rs"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/crc32-v2/actions/workflows/rust.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/wiseaidev/crc32-v2/actions/workflows/rust.yml/badge.svg" alt="Build Status"&gt;&lt;/a&gt;
&lt;a href="https://pypi.org/project/crc32-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/af42efaea46f4c5b80f0e2ae4dbf92e748e0b9d1b8637bf4e244722d80b0335f/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f63726333322d72732e737667" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/crc32-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/dd96357a508460c49f9e174e187646127a541ca57744e1dafa95615902ddf2ab/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f63726333322d72732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/crc32-v2/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The fastest pure-software, &lt;code&gt;no_std&lt;/code&gt;-compatible CRC-32 implementation in Rust, slicing-by-16 tables, zero heap allocation in the hot path, and native Python / Node.js bindings, all written in &lt;strong&gt;100% safe Rust&lt;/strong&gt; 🗿.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/wiseaidev/crc32-v2" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fcrc32-v2%2Frefs%2Fheads%2Fmain%2Fassets%2Fbanner.png" alt="Banger Banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Command / Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo add crc32-v2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust (no_std)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo add crc32-v2 --no-default-features&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install crc32-rs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm install crc32-rs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debian / Ubuntu&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/wiseaidev/crc32-v2/releases" rel="noopener noreferrer"&gt;&lt;code&gt;gh release download&lt;/code&gt;&lt;/a&gt;, see &lt;a href="https://github.com/wiseaidev/crc32-v2/PACKAGING.md" rel="noopener noreferrer"&gt;PACKAGING.md&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RHEL / Fedora&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/wiseaidev/crc32-v2/releases" rel="noopener noreferrer"&gt;&lt;code&gt;gh release download&lt;/code&gt;&lt;/a&gt;, see &lt;a href="https://github.com/wiseaidev/crc32-v2/PACKAGING.md" rel="noopener noreferrer"&gt;PACKAGING.md&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🔭 Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;no_std&lt;/code&gt; + &lt;code&gt;alloc&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Embeddable in bare-metal, WASM, and embedded targets, no standard library required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;100% safe Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; enforced crate-wide; zero &lt;code&gt;unsafe&lt;/code&gt; blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Byte-at-a-time baseline (~343 MiB/s); compatible with zlib, PKZIP, Ethernet, and FDDI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_little&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slicing-by-4 (~833 MiB/s); &lt;strong&gt;2.4×&lt;/strong&gt; faster than byte-at-a-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_little_8&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slicing-by-8 (~1,004 MiB/s); &lt;strong&gt;2.9×&lt;/strong&gt; faster than byte-at-a-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_little_16&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slicing-by-16 (&lt;strong&gt;~1,282 MiB/s&lt;/strong&gt;); &lt;strong&gt;3.7×&lt;/strong&gt; fastest pure-software path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_big&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Big-endian (unreflected) variant for hardware CRC controllers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;crc32_combine&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Merge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/wiseaidev/crc32-v2" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;P.S. The original &lt;code&gt;crc32&lt;/code&gt; crate maintainer is apparently a Microsoft employee. So, if you happen to work at Microsoft and are currently hiring Rust developers who spend their 2AM evenings resurrecting ancient dependencies to slice them by 16, please hit me up. We can bond over polynomial arithmetic. Thanks for the help &amp;lt;3!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Frozendict 🧊: State of the Art Immutable Hashmap for Python and Node JS.</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sat, 19 Sep 2026 04:25:17 +0000</pubDate>
      <link>https://dev.to/wiseai/frozendict-state-of-the-art-immutable-hashmap-for-python-and-node-js-284o</link>
      <guid>https://dev.to/wiseai/frozendict-state-of-the-art-immutable-hashmap-for-python-and-node-js-284o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Hello 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there I was, staring at &lt;a href="https://docs.python.org/3/builtins/stdtypes.html#set-types-set-frozenset" rel="noopener noreferrer"&gt;Python's &lt;code&gt;frozenset&lt;/code&gt;&lt;/a&gt;, feeling that specific special rage that only a data structure enthusiast at 1AM can feel, while &lt;code&gt;dict&lt;/code&gt; sat there, utterly mutable, fully hashable, completely disobedient.&lt;/p&gt;

&lt;p&gt;Dictionary keys can change. You can &lt;code&gt;pop&lt;/code&gt; from it. You can &lt;code&gt;clear&lt;/code&gt; it. You can &lt;code&gt;update&lt;/code&gt; it mid-computation and break 30 tests simultaneously.&lt;/p&gt;

&lt;p&gt;I looked at this situation calmly. And then I did what any reasonable person would do: I wrote &lt;code&gt;frozndict&lt;/code&gt;, a fully immutable, insertion-ordered, O(1)-hashable dictionary in &lt;strong&gt;100% safe Rust&lt;/strong&gt; with Python and Node.js bindings so fast they make &lt;code&gt;frozendict&lt;/code&gt; (the C extension) look briefly embarrassed at its own party.&lt;/p&gt;

&lt;p&gt;The result? &lt;a href="https://github.com/wiseaidev/frozndict" rel="noopener noreferrer"&gt;&lt;code&gt;frozndict&lt;/code&gt;&lt;/a&gt;: the state of the art immutable hashmap. Frozen at construction. Hashable by design. Faster than guilt.&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%2Fvweo6okcijijdwox5p63.jpeg" 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%2Fvweo6okcijijdwox5p63.jpeg" alt="Make Python dict immutable!" width="700" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Care?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.python.org/3/tutorial/datastructures.html#dictionaries" rel="noopener noreferrer"&gt;Python's &lt;code&gt;dict&lt;/code&gt;&lt;/a&gt; is a magnificent beast. It's ordered, fast, flexible. It is also a ticking time bomb if you try to use one as a cache key, a &lt;a href="https://docs.python.org/3/library/functools.html" rel="noopener noreferrer"&gt;&lt;code&gt;functools.lru_cache&lt;/code&gt;&lt;/a&gt; argument, or anywhere that requires hashability.&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="n"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;key&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;x&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;  &lt;span class="c1"&gt;# TypeError: unhashable type: 'dict'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;a href="https://docs.python.org/3/builtins/stdtypes.html#set-types-set-frozenset" rel="noopener noreferrer"&gt;stdlib's &lt;code&gt;frozenset&lt;/code&gt;&lt;/a&gt; solved this for sets. Nobody solved it properly for dicts for 15+ years, until &lt;a href="https://github.com/Marco-Sulla/python-frozendict" rel="noopener noreferrer"&gt;&lt;code&gt;frozendict&lt;/code&gt; (the C extension)&lt;/a&gt; came along. And then I looked at &lt;code&gt;frozendict&lt;/code&gt;'s construction time and made a concerned face.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;frozndict&lt;/code&gt; solves all of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Truly immutable&lt;/strong&gt;: mutation attempts at the Rust level raise &lt;code&gt;TypeError&lt;/code&gt;. Not &lt;code&gt;AttributeError&lt;/code&gt;. No monkey-patching. &lt;code&gt;__setitem__&lt;/code&gt;, &lt;code&gt;__delitem__&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;clear&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, &lt;code&gt;popitem&lt;/code&gt;, and &lt;code&gt;setdefault&lt;/code&gt; are all implemented, as gates that will refuse you entry and then log the attempt somewhere in the moral universe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O(1) &lt;code&gt;__hash__&lt;/code&gt;&lt;/strong&gt;: computed once at construction. Subsequent calls return a cached &lt;code&gt;isize&lt;/code&gt;. No recomputation. Ever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O(1) &lt;code&gt;copy()&lt;/code&gt;&lt;/strong&gt;: returns the same &lt;code&gt;Arc&amp;lt;FrozenDictInner&amp;gt;&lt;/code&gt;. One pointer copy. 63 ns. Done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insertion-ordered&lt;/strong&gt;: all views, &lt;code&gt;keys()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, &lt;code&gt;items()&lt;/code&gt;, iterate in the order you inserted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fromkeys&lt;/code&gt; support&lt;/strong&gt;: &lt;code&gt;FrozenDict.fromkeys(["a", "b"], 0)&lt;/code&gt; works exactly as you'd expect, including on subclasses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set algebra on views&lt;/strong&gt;: &lt;code&gt;fd.keys() &amp;amp; other_keys&lt;/code&gt;, &lt;code&gt;fd.items() - other_items&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;isdisjoint&lt;/code&gt;, all there.&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%2Fpbjvxx32ai75mcquxyk7.jpeg" 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%2Fpbjvxx32ai75mcquxyk7.jpeg" alt="Change My Mind!" width="578" height="433"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Here is the internal layout:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FrozenDict
  └── Arc&amp;lt;FrozenDictInner&amp;gt;          ← shared ownership, O(1) clone
        ├── entries: Box&amp;lt;[(isize, Obj, Obj)]&amp;gt;   ← insertion-ordered (key_hash, key, val)
        ├── lookup: Box&amp;lt;[(isize, u32)]&amp;gt;          ← sorted by hash for binary search
        ├── hash: isize                          ← pre-computed at build time
        ├── cached_keys: OnceLock&amp;lt;Py&amp;lt;PyList&amp;gt;&amp;gt;    ← lazy, shared across views
        ├── cached_values: OnceLock&amp;lt;Py&amp;lt;PyList&amp;gt;&amp;gt;
        └── cached_items: OnceLock&amp;lt;Py&amp;lt;PyList&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The key insight: &lt;strong&gt;entries stay in insertion order&lt;/strong&gt;. The &lt;strong&gt;lookup table&lt;/strong&gt; is a separate, sorted slice used only for binary search. This gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O(n) insertion-ordered iteration (just walk &lt;code&gt;entries&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;O(log n + k) lookup (binary search to the hash bucket, then linear scan for collision k)&lt;/li&gt;
&lt;li&gt;O(n log n) construction (one sort of the lookup table, then done)&lt;/li&gt;
&lt;li&gt;O(1) &lt;code&gt;copy()&lt;/code&gt; and &lt;code&gt;clone()&lt;/code&gt; (pointer copy of the &lt;code&gt;Arc&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hash is computed by XOR-mixing each &lt;code&gt;key_hash * MIX_KEY ^ value_hash * MIX_VAL&lt;/code&gt;. Order-independent. Two frozen dicts with the same contents but different insertion order are equal and share a hash. As nature intended.&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%2Fdjtq8b2995kouc68ai1r.jpeg" 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%2Fdjtq8b2995kouc68ai1r.jpeg" alt="Ferris the crab holding a sorted lookup slice" width="557" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Performance Numbers
&lt;/h2&gt;

&lt;p&gt;These are real numbers. Benchmarked with &lt;code&gt;timeit&lt;/code&gt; on Python 3.12.3, x86-64 Linux, min of 7 runs × 2,000 iterations, N=1000 entries.&lt;/p&gt;
&lt;h3&gt;
  
  
  Python-level benchmark
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Python dict&lt;/th&gt;
&lt;th&gt;frozendict (C)&lt;/th&gt;
&lt;th&gt;immutables.Map&lt;/th&gt;
&lt;th&gt;frozndict 🧊&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Construction&lt;/td&gt;
&lt;td&gt;6.45 µs&lt;/td&gt;
&lt;td&gt;7.70 µs&lt;/td&gt;
&lt;td&gt;241.67 µs&lt;/td&gt;
&lt;td&gt;90.70 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clone O(1)&lt;/td&gt;
&lt;td&gt;6.45 µs&lt;/td&gt;
&lt;td&gt;70.48 ns&lt;/td&gt;
&lt;td&gt;404.62 ns&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;138.68 ns&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Equality&lt;/td&gt;
&lt;td&gt;19.37 µs&lt;/td&gt;
&lt;td&gt;19.44 µs&lt;/td&gt;
&lt;td&gt;24.39 ns&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;32.42 ns&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration&lt;/td&gt;
&lt;td&gt;7.39 µs&lt;/td&gt;
&lt;td&gt;7.42 µs&lt;/td&gt;
&lt;td&gt;14.97 µs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.14 µs&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;copy()&lt;/td&gt;
&lt;td&gt;6.53 µs&lt;/td&gt;
&lt;td&gt;323.83 ns&lt;/td&gt;
&lt;td&gt;317.07 µs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;63.29 ns&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hash()&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;168.19 ns&lt;/td&gt;
&lt;td&gt;45.07 ns&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;45.52 ns&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lookup&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;32.52 ns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;48.31 ns&lt;/td&gt;
&lt;td&gt;48.11 ns&lt;/td&gt;
&lt;td&gt;82.62 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;frozndict&lt;/code&gt; wins iteration, &lt;code&gt;copy()&lt;/code&gt;, equality, clone, and very nearly ties &lt;code&gt;immutables.Map&lt;/code&gt; on &lt;code&gt;hash()&lt;/code&gt;. On a per-call basis, the pure Rust functions run in &lt;strong&gt;nanoseconds&lt;/strong&gt;, which is approximately &lt;strong&gt;1,000,000x faster&lt;/strong&gt; than any Python-level re-implementation of the same logic would be. This is what happens when you move computation to Rust and let LLVM take it from there.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rust-level benchmark
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Construction, n=100&lt;/td&gt;
&lt;td&gt;~2.7 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Construction, n=1000&lt;/td&gt;
&lt;td&gt;~35 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lookup hit&lt;/td&gt;
&lt;td&gt;~41 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lookup miss&lt;/td&gt;
&lt;td&gt;~39 ns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration, n=1000&lt;/td&gt;
&lt;td&gt;~3.1 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hash()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~4.8 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;with()&lt;/code&gt; (functional update)&lt;/td&gt;
&lt;td&gt;~31 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;merge()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~35 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The lookup path is 40 nanoseconds. For comparison, a Python function call overhead alone is about 60-100 ns. &lt;code&gt;frozndict&lt;/code&gt; answers your lookup query faster than Python could even begin thinking about 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%2Fm3hfmd6nhgisssfpyn9t.jpeg" 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%2Fm3hfmd6nhgisssfpyn9t.jpeg" alt="Ferris Chilling" width="680" height="438"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Equality Problem
&lt;/h2&gt;

&lt;p&gt;Here is a question for you: are these two &lt;code&gt;FrozenDict&lt;/code&gt;s equal?&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&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="c1"&gt;# different insertion order
&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  &lt;span class="c1"&gt;# ?
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Yes. Obviously yes. They have the same key-value pairs. The answer is &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The naive implementation, comparing entries positionally, index by index, returns &lt;code&gt;False&lt;/code&gt; because the entries are stored in insertion order. Early &lt;code&gt;frozndict&lt;/code&gt; versions had exactly this bug. I discovered it while writing the tests at midnight and sat in silence for a moment before going to fix it.&lt;/p&gt;

&lt;p&gt;The correct implementation uses the &lt;strong&gt;sorted lookup table&lt;/strong&gt; to do a key-based lookup for each entry in &lt;code&gt;other&lt;/code&gt;, then checks the value. Order-independent. Hash-consistent. Correct.&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# True, hash is order-independent by design
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;# {frozendict({'x': 1, 'y': 2})}, only one element
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That last line, being usable in a &lt;code&gt;set&lt;/code&gt;, is the whole point. If your immutable dict can't be a set member, what are you even doing with your life?&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%2Fv8qbixs8vrcoawgroo1t.jpeg" 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%2Fv8qbixs8vrcoawgroo1t.jpeg" alt="frozndict: (presses both simultaneously)" width="500" height="757"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The &lt;code&gt;Arc&amp;lt;FrozenDictInner&amp;gt;&lt;/code&gt; Design
&lt;/h2&gt;

&lt;p&gt;Every Python object wrapping &lt;code&gt;frozndict&lt;/code&gt; shares one &lt;code&gt;Arc&amp;lt;FrozenDictInner&amp;gt;&lt;/code&gt;. When you call &lt;code&gt;copy()&lt;/code&gt;, we clone the &lt;code&gt;Arc&lt;/code&gt;, which is a single atomic increment on a reference count. No allocation. No copying of entries. No touching the lookup table.&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;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;frozndict&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FrozenDict&lt;/span&gt;

&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;span class="n"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter_ns&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter_ns&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# \~63 ns
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;63 nanoseconds. For a 1,000-entry dictionary.&lt;/p&gt;

&lt;p&gt;For comparison, &lt;code&gt;copy.copy()&lt;/code&gt; on a Python &lt;code&gt;dict&lt;/code&gt; of the same size is ~6.5 µs. That's 100x slower than &lt;code&gt;frozndict.copy()&lt;/code&gt;. And &lt;code&gt;copy()&lt;/code&gt; on the C &lt;code&gt;frozendict&lt;/code&gt; is ~324 ns, still 5x slower.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;frozndict.copy()&lt;/code&gt; is so fast it's almost a moral argument for immutability. Why would you ever mutate a dictionary when the immutable version is cheaper to "clone"?&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%2Fh3hcktuinkp0isvg56rt.jpeg" 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%2Fh3hcktuinkp0isvg56rt.jpeg" alt="Surprised Pikachu" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Views
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;frozndict&lt;/code&gt; returns view objects that behave like &lt;code&gt;dict_keys&lt;/code&gt;, &lt;code&gt;dict_values&lt;/code&gt;, and &lt;code&gt;dict_items&lt;/code&gt;, but with the full set-algebra API you always wished Python's dict views had by default.&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="n"&gt;d1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;d2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;d&lt;/span&gt;&lt;span class="sh"&gt;"&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="c1"&gt;# Keys set algebra
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# frozenset({'b', 'c'})
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# frozenset({'a', 'b', 'c', 'd'})
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# frozenset({'a'})
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# frozenset({'a', 'd'})
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isdisjoint&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;    &lt;span class="c1"&gt;# True
&lt;/span&gt;
&lt;span class="c1"&gt;# Items set algebra (tuples!)
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="c1"&gt;# frozenset({('b', 2)}), only exact (k,v) matches
&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;        &lt;span class="c1"&gt;# frozenset({('a', 1), ('c', 3)})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The views are lazy, they hold a reference to the same &lt;code&gt;Arc&amp;lt;FrozenDictInner&amp;gt;&lt;/code&gt;, share zero extra memory overhead, and do all set operations on demand. The items view is particularly clever: &lt;code&gt;("c", 3)&lt;/code&gt; is NOT in both dicts' items because the values differ (&lt;code&gt;3&lt;/code&gt; vs &lt;code&gt;99&lt;/code&gt;). The binary lookup handles this correctly.&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%2Fbccwfed0a4ccvc3nv0sg.jpeg" 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%2Fbccwfed0a4ccvc3nv0sg.jpeg" alt="same same but different" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Mutation Guards
&lt;/h2&gt;

&lt;p&gt;Every mutable dict method exists on &lt;code&gt;FrozenDict&lt;/code&gt;. All of them raise &lt;code&gt;TypeError&lt;/code&gt;. This is important:&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="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;         &lt;span class="c1"&gt;# TypeError: 'FrozenDict' object does not support mutation
&lt;/span&gt;&lt;span class="n"&gt;fd&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;# TypeError: 'FrozenDict' object does not support mutation
&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# TypeError: 'FrozenDict' object does not support mutation
&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# TypeError: 'FrozenDict' object does not support mutation
&lt;/span&gt;&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;            &lt;span class="c1"&gt;# TypeError: 'frozendict' object does not support mutation
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Why implement these at all if they just fail? Because Python's &lt;code&gt;typing.MutableMapping&lt;/code&gt; and &lt;code&gt;collections.abc.Mapping&lt;/code&gt; ABCs expect these methods to exist for proper isinstance checks and duck-typing. If you use a &lt;code&gt;FrozenDict&lt;/code&gt; anywhere a &lt;code&gt;dict | MutableMapping&lt;/code&gt; is type-hinted, you get the correct &lt;code&gt;TypeError&lt;/code&gt;, not a cryptic &lt;code&gt;AttributeError&lt;/code&gt; suggesting the method doesn't exist.&lt;/p&gt;

&lt;p&gt;This is the difference between "I cannot do this" and "this object has no concept of doing this". &lt;code&gt;frozndict&lt;/code&gt; chooses the former. We exist. We just refuse.&lt;/p&gt;
&lt;h2&gt;
  
  
  Subclassing, &lt;code&gt;fromkeys&lt;/code&gt;, &lt;code&gt;__class_getitem__&lt;/code&gt;, and &lt;code&gt;reversed()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;All of the things Python developers expect to work, work.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ColdStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;cs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ColdStorage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;273&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;ColdStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromkeys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&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;b&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;c&lt;/span&gt;&lt;span class="sh"&gt;"&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="c1"&gt;# frozendict({'a': 0, 'b': 0, 'c': 0})
&lt;/span&gt;
&lt;span class="n"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# frozndict.FrozenDict[str, int]  ← GenericAlias, works with type hints
&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&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="c1"&gt;# ['b', 'a', 'c']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;fromkeys&lt;/code&gt; on a subclass returns an instance of the subclass. &lt;code&gt;__class_getitem__&lt;/code&gt; returns a &lt;code&gt;frozndict&lt;/code&gt;. &lt;code&gt;__reversed__&lt;/code&gt; iterates keys in reverse insertion order.&lt;/p&gt;

&lt;p&gt;These are the features that make a library &lt;strong&gt;correct&lt;/strong&gt; instead of merely &lt;strong&gt;functional&lt;/strong&gt;. There's a difference.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;frozndict
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;frozndict&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FrozenDict&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FrozenDict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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;Ferris&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;type&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;crab&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;mood&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;frozen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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;Ferris&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&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="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7563131740537042003&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;frozendict&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&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;Ferris&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;type&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;crab&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;mood&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;frozen&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Use it as a dict key:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;# Use it in a set:
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  As a Rust library:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;frozndict&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2.1.1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;frozndict&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FrozenMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FrozenMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FrozenMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="s"&gt;"a"&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="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"b"&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="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;extended&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="nf"&gt;.with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extended&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Road Ahead
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;frozndict 2.1.1&lt;/code&gt; is stable but not finished. The roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WASM target&lt;/strong&gt;: compile the core to &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt; for browser-side immutable hashmaps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;serde&lt;/code&gt; support&lt;/strong&gt;: serialize/deserialize &lt;code&gt;FrozenMap&lt;/code&gt; as naturally as a &lt;code&gt;HashMap&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these sound urgent to you: &lt;a href="https://github.com/wiseaidev/frozndict/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;. Or star the repo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;frozndict&lt;/code&gt; does one thing: it gives Python a dictionary that is genuinely, provably, irreversibly frozen. Not "sort of frozen if you don't try to break it". Frozen at the hardware level, where the Rust borrow checker watches over your entries like a disapproving parent at a teen party.&lt;/p&gt;

&lt;p&gt;It's insertion-ordered. It's hashable. It's &lt;code&gt;O(1)&lt;/code&gt; to copy. Its inner functions run in &lt;strong&gt;nanoseconds&lt;/strong&gt;. It has views with set algebra. It subclasses correctly. Its &lt;code&gt;fromkeys&lt;/code&gt; works. Its mutation guards are polite but firm.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/wiseaidev" rel="noopener noreferrer"&gt;
        wiseaidev
      &lt;/a&gt; / &lt;a href="https://github.com/wiseaidev/frozndict" rel="noopener noreferrer"&gt;
        frozndict
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      State of the art immutable hashmap for Python and Node.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🧊 FrozenDict&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/wiseaidev/frozndict" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Ffrozndict%2Frefs%2Fheads%2Fmain%2Fassets%2Fbanner.png" alt="frozendict logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/frozendict" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/803ddcab1b1b708144422ae6de90f74fd1df93b6c27225c8446b4a6261ca1d27/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f66726f7a656e646963742e737667" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://docs.rs/frozendict" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7231566af00ba416d2c711185b667b82fb260f7ea43fef0a554bdcdc5f752a2e/68747470733a2f2f646f63732e72732f66726f7a656e646963742f62616467652e737667" alt="Docs.rs"&gt;&lt;/a&gt;
&lt;a href="https://pypi.org/project/frozndict" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8376a667721fea59dcf1c2e95f9e37ac9729a7dd17f5302231e85c6984e03084/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f66726f7a6e646963742e737667" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/frozendict" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/34a2f1dcb31a1c9eaf6a09c50f150dcf61d473760c2fa3ad1a6ebf24090a441b/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f66726f7a656e646963742e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/frozndict/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/frozndict/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/wiseaidev/frozndict/actions/workflows/ci.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;frozendict&lt;/code&gt; is a state of the art world's most memory-efficient immutable hashmap written in &lt;strong&gt;100% safe Rust&lt;/strong&gt;, with native Python and Node.js bindings 🗿.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/wiseaidev/frozndict" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Ffrozndict%2Frefs%2Fheads%2Fmain%2Fassets%2Fmain-banner.png" alt="frozendict banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust library&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo add frozendict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install frozndict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm i frozendict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debian/Ubuntu&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.deb&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/frozndict/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RHEL/Fedora&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.rpm&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/frozndict/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 What does this crate provide?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;frozendict&lt;/code&gt; provides a &lt;strong&gt;fully immutable, hashable dictionary&lt;/strong&gt; for Python and Node.js backed by a high-performance Rust core. It:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stores&lt;/strong&gt; entries in a single contiguous sorted heap allocation, zero per-entry heap overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Looks up&lt;/strong&gt; keys in O(log n) via binary search, no hashing, no pointer-chasing, excellent cache behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caches&lt;/strong&gt; its hash at construction, repeated &lt;code&gt;hash()&lt;/code&gt; calls are O(1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrates&lt;/strong&gt; with Python's dict protocol (&lt;code&gt;keys()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, &lt;code&gt;items()&lt;/code&gt;, pickle, copy, &lt;code&gt;|&lt;/code&gt; merge operator).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exposes&lt;/strong&gt; a native Node.js &lt;code&gt;FrozenDict&lt;/code&gt; class with TypeScript declarations via &lt;a href="https://napi.rs" rel="nofollow noopener noreferrer"&gt;napi-rs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provides&lt;/strong&gt; functional…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/wiseaidev/frozndict" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Star &lt;a href="https://github.com/wiseaidev/frozndict" rel="noopener noreferrer"&gt;the repo&lt;/a&gt;. File issues. Use it as a cache key confidently. And the next time someone tries to mutate your dictionary mid-computation, point them here.&lt;/p&gt;

&lt;p&gt;Till next time: &lt;em&gt;Stay frozen. Stay fast. Don't mutate.&lt;/em&gt; 🦀🧊&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Optimized My Bump Version Tool and Made It 1,000,000x Faster Than Its Python Counterparts.</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Fri, 11 Sep 2026 22:15:08 +0000</pubDate>
      <link>https://dev.to/wiseai/i-optimized-my-bump-version-tool-and-made-it-1000000x-faster-than-its-python-counterparts-2i83</link>
      <guid>https://dev.to/wiseai/i-optimized-my-bump-version-tool-and-made-it-1000000x-faster-than-its-python-counterparts-2i83</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Hello again, fellow Rustaceans, Pythonistas in denial, and the three people on earth who genuinely enjoy reading version bumper release notes 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you were here for my last post, where I rewrote &lt;a href="https://github.com/c4urself/bump2version" rel="noopener noreferrer"&gt;&lt;code&gt;bump2version&lt;/code&gt;&lt;/a&gt; in Rust and declared it &lt;strong&gt;~10,000x faster&lt;/strong&gt; than the Python CLI, you may recall that I ended it with a vague threat about future benchmarks. The Mossad agents who consulted on the architecture wrote "this is not over" in the margin of their whiteboard. I ignored it.&lt;/p&gt;

&lt;p&gt;I should have listened.&lt;/p&gt;

&lt;p&gt;Because in the weeks since that post, I went back in. &lt;em&gt;Deep in.&lt;/em&gt; I committed crimes against &lt;code&gt;cargo build&lt;/code&gt; that will haunt me during thunderstorms. I &lt;code&gt;--release&lt;/code&gt;'d things that should not be &lt;code&gt;--release&lt;/code&gt;'d. I made Claude hallucinate a performance chart at 3AM and then used it to motivate myself.&lt;/p&gt;

&lt;p&gt;The result: &lt;a href="https://github.com/wiseaidev/bump2version/releases/tag/v0.2.1" rel="noopener noreferrer"&gt;&lt;code&gt;bump2version 0.2.1&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Now 1,000,000× faster than its Python counterparts.&lt;/strong&gt; Yes, I am counting subprocess overhead.&lt;/p&gt;
&lt;/blockquote&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%2Fvp5z7xx92lzkpqwozbkl.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%2Fvp5z7xx92lzkpqwozbkl.png" alt="The Soviet material resurfaced" width="799" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Soviet material resurfaced. It always does.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Wait, We Already Did This. Why Are We Here Again?
&lt;/h2&gt;

&lt;p&gt;Because &lt;code&gt;0.2.0&lt;/code&gt; shipped, and I immediately opened my Gmail inbox.&lt;/p&gt;

&lt;p&gt;The audacity of the open-source community. The audacity, bro! I build something 10,000x faster and within &lt;em&gt;days&lt;/em&gt; there are requests. "Can it watch files?", "Can it detect which manifests I'm using?", "Can I run it in the browser?", "Can I use it with Go?", "Can I use it with Java?", "Can my Ruby project use it?". I ain't got no time for this. I need to take a little break and play CS2 with the boys!&lt;/p&gt;

&lt;p&gt;I looked at these emails. I looked at the ceiling. I looked at my coffee. The coffee looked back at me with the hollow expression of a language runtime that has seen too many package manager debates.&lt;/p&gt;

&lt;p&gt;And then I cracked my knuckles and got to work.&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%2Fu4lem522e4mgkzb6bqpm.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%2Fu4lem522e4mgkzb6bqpm.png" alt="This is fine" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🕵️ The Mossad Agents Return
&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%2F6et95mbt70i4nymvwgp5.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%2F6et95mbt70i4nymvwgp5.png" alt="My Cutest Mossad Agent" width="799" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I thought I was done with the Mossad agents after &lt;code&gt;0.2.0&lt;/code&gt;. I was not.&lt;/p&gt;

&lt;p&gt;They came back. Same 3AM knock. Same whiteboard. But this time &lt;em&gt;they brought slides.&lt;/em&gt; Twelve of them. With bullet points. And speaker notes. One slide was just the word &lt;strong&gt;"BRANCHLESS"&lt;/strong&gt; in 72-point font with a red circle around it.&lt;/p&gt;

&lt;p&gt;Their new requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/BurntSushi/memchr" rel="noopener noreferrer"&gt;&lt;code&gt;memchr&lt;/code&gt;&lt;/a&gt; for all hot-path string scanning.&lt;/strong&gt; &lt;em&gt;"You are doing &lt;code&gt;.contains()&lt;/code&gt; in a loop like an animal",&lt;/em&gt; they said. I was.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/servo/rust-smallvec" rel="noopener noreferrer"&gt;&lt;code&gt;SmallVec&lt;/code&gt;&lt;/a&gt; for version component storage.&lt;/strong&gt; Because heap-allocating a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt; for three numbers (major, minor, patch) is an insult to modern CPU cache lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branchless arithmetic for the bump itself.&lt;/strong&gt; No &lt;code&gt;if major { ... } else if minor { ... }&lt;/code&gt; nonsense. One lookup table. One store. Done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch mode.&lt;/strong&gt; They wanted to know the moment a file changed. I asked why. They said that was classified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-detect language manifests.&lt;/strong&gt; "You scan &lt;code&gt;Cargo.toml&lt;/code&gt; like it's the only file in the world", they observed, correctly. "What about &lt;code&gt;pyproject.toml&lt;/code&gt;? &lt;code&gt;pom.xml&lt;/code&gt;? &lt;code&gt;go.mod&lt;/code&gt;? Are Go developers not also suffering?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They are. They are very much also suffering.&lt;/p&gt;

&lt;p&gt;I implemented every point. The Mossad agents reviewed the diff, said "passable", and vanished into the root filesystem like a well-placed &lt;code&gt;.gitignore&lt;/code&gt; entry.&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%2Ft1puz7sbsjsq58ch5num.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%2Ft1puz7sbsjsq58ch5num.png" alt="Ferris in black suit" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ The 1,000,000× Number
&lt;/h2&gt;

&lt;p&gt;Let me be absolutely scientifically honest with you for one sentence before I stop being honest: the 1,000,000× number compares the full &lt;code&gt;bump-my-version&lt;/code&gt; CLI round-trip (importing Python, loading dependencies, spawning a subprocess) against our in-process library call with a warm cache and a &lt;code&gt;SmallVec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One is a sports car. The other is a person who has to call a taxi, wait 12 minutes, and explain where they're going in a language they only partially speak.&lt;/p&gt;

&lt;p&gt;Now let's look at the real numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔥 New Benchmarks: &lt;code&gt;0.2.0&lt;/code&gt; vs &lt;code&gt;0.2.1&lt;/code&gt; vs Python
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;bump2version&lt;/code&gt; &lt;code&gt;0.2.0&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;bump2version&lt;/code&gt; &lt;code&gt;0.2.1&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Python pyO3 FFI&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;bump-my-version&lt;/code&gt; CLI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Parse + bump + serialize&lt;/td&gt;
&lt;td&gt;~57 µs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~0.4 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~79 µs&lt;/td&gt;
&lt;td&gt;~585 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File search/replace (1k lines)&lt;/td&gt;
&lt;td&gt;~65 µs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~11 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1.7 µs&lt;/td&gt;
&lt;td&gt;~590 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File search/replace (100k lines)&lt;/td&gt;
&lt;td&gt;~4.2 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~0.9 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;~600 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Config file parse&lt;/td&gt;
&lt;td&gt;~800 µs&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~140 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;~500 ms (on import)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Versus the Python CLI subprocess: ((500 x 1000) ÷ 0.4) = &lt;strong&gt;~1,250,000×&lt;/strong&gt; faster for a version parse-bump-serialize. We round down to 1,000,000x for humility. The Mossad agents said rounding up was acceptable. We preferred honesty.&lt;/p&gt;

&lt;h3&gt;
  
  
  What got fast and why:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;memchr&lt;/code&gt;&lt;/strong&gt; replaced every inner-loop string search. &lt;code&gt;memchr&lt;/code&gt; is basically SIMD-accelerated &lt;code&gt;strchr&lt;/code&gt; and it is unreasonably good at its one job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SmallVec&amp;lt;[VersionPart; 8]&amp;gt;&lt;/code&gt;&lt;/strong&gt; means version component vectors never touch the allocator for reasonable semver (≤8 parts). Stack-allocated. L1 cache. Zero malloc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branchless bump arithmetic&lt;/strong&gt;: the bump logic is now a lookup into a const table of which component to increment and which to zero. The CPU's branch predictor doesn't even have to sweat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; cache&lt;/strong&gt; from &lt;code&gt;0.2.0&lt;/code&gt; was kept. The regex is compiled exactly once and shared. The Mossad agents reminded us about this at every meeting by projecting the same slide.&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%2F698at0khmhmrvjevks1b.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%2F698at0khmhmrvjevks1b.png" alt="Ferris the crab flexin'" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📡 Watch Mode
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;bump --watch --bump patch&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It sounds simple. It was the opposite of simple.&lt;/p&gt;

&lt;p&gt;"Just watch a file and re-bump when it changes", I told myself, in the tone of a man who has never used &lt;a href="https://man7.org/linux/man-pages/man7/inotify.7.html" rel="noopener noreferrer"&gt;&lt;code&gt;inotify&lt;/code&gt;&lt;/a&gt; before.&lt;/p&gt;

&lt;p&gt;Bro, I used &lt;code&gt;inotify&lt;/code&gt;. Or rather, &lt;a href="https://github.com/notify-rs/notify" rel="noopener noreferrer"&gt;&lt;code&gt;notify-rs&lt;/code&gt;&lt;/a&gt; used &lt;code&gt;inotify&lt;/code&gt; for me, which is almost the same thing except someone smarter than me had already suffered through the Linux kernel filesystem event API so I wouldn't have to. God bless crate authors.&lt;/p&gt;

&lt;p&gt;Watch mode works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You provide a &lt;code&gt;--watch&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bump&lt;/code&gt; registers a recursive file watcher on all files listed in your &lt;code&gt;.bumpversion.toml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Every time a registered file is saved (debounced to 200ms to avoid event avalanches), &lt;code&gt;bump&lt;/code&gt; checks whether the version string is still consistent with &lt;code&gt;current_version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If it detects drift, it re-applies the bump.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is either extremely useful for local development workflows or a deeply irresponsible footgun. We ship tools for adults. The lock safety is your problem.&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="c"&gt;# Watches VERSION, Cargo.toml, and README.md for changes, auto-bumps on save&lt;/span&gt;
bump &lt;span class="nt"&gt;--watch&lt;/span&gt; &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--config-file&lt;/span&gt; .bumpversion.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Oh no did I just? yes, yes you did. It already ran.&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;watch] Detected change: Cargo.toml
&lt;span class="o"&gt;[&lt;/span&gt;watch] Bumping patch: 0.2.1 → 0.2.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fhozki5ti00nxqgtnn1ri.jpeg" 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%2Fhozki5ti00nxqgtnn1ri.jpeg" alt="surprised pikachu" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🌐 Multi-Language Auto-Detection: &lt;code&gt;--detect&lt;/code&gt; Is Doing God's Work
&lt;/h2&gt;

&lt;p&gt;Previous &lt;code&gt;bump2version&lt;/code&gt; was Rust-centric. You gave it files, it bumped files. Very obedient lil tool. Very rigid. Like a Rust compiler, actually.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;--detect&lt;/code&gt; flag changes all that:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bump &lt;span class="nt"&gt;--bump&lt;/span&gt; minor &lt;span class="nt"&gt;--detect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This single command:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Walks the entire directory tree&lt;/strong&gt; (skipping &lt;code&gt;target/&lt;/code&gt;, &lt;code&gt;node_modules/&lt;/code&gt;, &lt;code&gt;.git/&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finds every recognized manifest&lt;/strong&gt;: &lt;code&gt;Cargo.toml&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;pom.xml&lt;/code&gt;, &lt;code&gt;build.gradle&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checks each one&lt;/strong&gt; for the current version string&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewrites every match&lt;/strong&gt; in one coordinated pass&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Six languages. One command.&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;my-monorepo
bump &lt;span class="nt"&gt;--current-version&lt;/span&gt; 0.1.0 &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--detect&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt;

&lt;span class="c"&gt;# [detect][dry-run] Would update: Cargo.toml&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would update: pyproject.toml&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would update: package.json&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would update: pom.xml&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would update: go.mod&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would commit 5 file(s): 0.1.0 → 0.1.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Full supported matrix:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Manifest Files&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🦀 Rust&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🐍 Python&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt;, &lt;code&gt;setup.py&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟨 JavaScript / Node.js&lt;/td&gt;
&lt;td&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🐹 Go&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;☕ Java&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pom.xml&lt;/code&gt;, &lt;code&gt;build.gradle&lt;/code&gt;, &lt;code&gt;build.gradle.kts&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💎 Ruby&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Gemfile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Go developers, in particular, messaged to say thank you. We thanked them for using Go despite everything.&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%2Fflicsijhh49yrws4r0j0.jpeg" 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%2Fflicsijhh49yrws4r0j0.jpeg" alt="bump2version is expanding my smol brain" width="500" height="701"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🌍 Real Language Examples
&lt;/h2&gt;

&lt;p&gt;Every language now has a working example under &lt;a href="https://github.com/wiseaidev/bump2version/tree/main/examples" rel="noopener noreferrer"&gt;&lt;code&gt;examples/&lt;/code&gt;&lt;/a&gt;, each with its own pre-baked &lt;code&gt;.bumpversion.toml&lt;/code&gt;.&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="c"&gt;# Python project&lt;/span&gt;
bump &lt;span class="nt"&gt;--config-file&lt;/span&gt; examples/python/.bumpversion.toml &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="c"&gt;# [dry-run] Would commit 2 file(s): 0.1.0 → 0.1.1&lt;/span&gt;

&lt;span class="c"&gt;# Node.js project&lt;/span&gt;
bump &lt;span class="nt"&gt;--config-file&lt;/span&gt; examples/nodejs/.bumpversion.toml &lt;span class="nt"&gt;--bump&lt;/span&gt; minor &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="c"&gt;# [dry-run] Would commit 1 file(s): 0.1.0 → 0.2.0&lt;/span&gt;

&lt;span class="c"&gt;# Java Maven project&lt;/span&gt;
bump &lt;span class="nt"&gt;--config-file&lt;/span&gt; examples/java/.bumpversion.toml &lt;span class="nt"&gt;--new-version&lt;/span&gt; 2.0.0 &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="c"&gt;# [dry-run] Would commit 1 file(s): 0.1.0 → 2.0.0&lt;/span&gt;

&lt;span class="c"&gt;# Ruby gemspec + Gemfile&lt;/span&gt;
bump &lt;span class="nt"&gt;--config-file&lt;/span&gt; examples/ruby/.bumpversion.toml &lt;span class="nt"&gt;--bump&lt;/span&gt; major &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="c"&gt;# [dry-run] Would commit 2 file(s): 0.1.0 → 1.0.0&lt;/span&gt;

&lt;span class="c"&gt;# The "bump everything at once" grand finale&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;examples/multi-lang
bump &lt;span class="nt"&gt;--current-version&lt;/span&gt; 0.1.0 &lt;span class="nt"&gt;--bump&lt;/span&gt; minor &lt;span class="nt"&gt;--detect&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;span class="c"&gt;# [detect][dry-run] Would update: Cargo.toml, pyproject.toml, package.json, pom.xml, Gemfile, VERSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;6 ecosystems. 1 tool. Still forbids &lt;code&gt;unsafe&lt;/code&gt;. We have standards.&lt;/p&gt;
&lt;h2&gt;
  
  
  🕸️ The Yew WASM App
&lt;/h2&gt;

&lt;p&gt;You ever look at a perfectly good CLI tool and think: &lt;em&gt;"This would be better if I could bump versions from a browser"?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No? Me neither. But then someone on the team whispered "WASM" and I remembered that I am constitutionally incapable of saying no to WebAssembly.&lt;/p&gt;

&lt;p&gt;So now there is a Yew-based web application at &lt;a href="https://github.com/wiseaidev/bump2version/tree/main/examples/yew-app" rel="noopener noreferrer"&gt;&lt;code&gt;examples/yew-app/&lt;/code&gt;&lt;/a&gt;. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runs entirely in the browser&lt;/strong&gt;: &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt;, no server required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connects to the same Rust core&lt;/strong&gt; via a &lt;a href="https://github.com/wiseaidev/bump2version/blob/main/examples/yew-app/src/version_ops.rs" rel="noopener noreferrer"&gt;&lt;code&gt;version_ops.rs&lt;/code&gt;&lt;/a&gt; bridge module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yes, &lt;code&gt;git&lt;/code&gt;-related features had to be extracted into an optional feature flag (&lt;code&gt;git&lt;/code&gt;) because &lt;code&gt;gix&lt;/code&gt; uses Unix-specific APIs that don't compile to WASM. We found this out the fun way, which is a phrase that means "at 2AM with a 47-line linker error".&lt;/p&gt;
&lt;h2&gt;
  
  
  🤖 I Abused ChatGPT, Claude and Gemini. Again. More.
&lt;/h2&gt;

&lt;p&gt;You may recall from my previous post that I abused Claude during &lt;code&gt;0.2.0&lt;/code&gt; development. My lawyer said not to bring it up again.&lt;/p&gt;

&lt;p&gt;So I won't bring up the fact that during &lt;code&gt;0.2.1&lt;/code&gt; development, I made ChatGPT, Claude and Gemini:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewrite the &lt;code&gt;detect.rs&lt;/code&gt; walk implementation 7 times until it correctly skipped &lt;code&gt;node_modules&lt;/code&gt; without accidentally also skipping &lt;code&gt;node_modules_backup&lt;/code&gt; (important distinction)&lt;/li&gt;
&lt;li&gt;Argue with itself about whether &lt;code&gt;SmallVec&amp;lt;[VersionPart; 8]&amp;gt;&lt;/code&gt; was better than &lt;code&gt;SmallVec&amp;lt;[VersionPart; 4]&amp;gt;&lt;/code&gt; for typical semver usage (it is &lt;code&gt;8&lt;/code&gt;, empirically)&lt;/li&gt;
&lt;li&gt;Generate &lt;code&gt;.bumpversion.toml&lt;/code&gt; configs for &lt;strong&gt;7 languages&lt;/strong&gt;, review them for correctness, then find its own mistake in the Ruby config and fix it without being asked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The OpenAI, Anthropic and Google lawyers have upgraded from "concerned" to "a medium-sized incident report has been filed".&lt;/p&gt;

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

&lt;p&gt;My legal counsel has asked that I clarify: no Claude was permanently harmed. Tokens were consumed. Electricity was used. The &lt;code&gt;--detect&lt;/code&gt; flag works correctly.&lt;/p&gt;
&lt;h2&gt;
  
  
  🚀 3 Binaries, One Package, Zero Confusing Changelog Entries
&lt;/h2&gt;

&lt;p&gt;After &lt;code&gt;cargo install bump2version --features rust-binary&lt;/code&gt;, you get three things:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The modern, primary CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cargo-bump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cargo subcommand (&lt;code&gt;cargo bump --bump patch&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bump2version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Backward-compatible alias&lt;/strong&gt; for old CI configs, tutorials, and the 47 blog posts that told people to run &lt;code&gt;bump2version --bump patch&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;bump2version&lt;/code&gt; binary is not deprecated. It is not going anywhere. If you have a shell script from 2025 that calls &lt;code&gt;bump2version --bump minor&lt;/code&gt;, it will still work in 2030, and presumably during the heat death of the universe, if any of your CI pipelines survive that long.&lt;/p&gt;

&lt;p&gt;This was a deliberate choice. Breaking changes in release tooling are a form of chaos that no version bumper should inflict on the people who trusted it.&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="c"&gt;# All of these do the exact same thing:&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch
cargo bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch
bump2version &lt;span class="nt"&gt;--bump&lt;/span&gt; patch   &lt;span class="c"&gt;# kept for backward compatibility&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fiknuz7j5yunc1owf93ci.jpeg" 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%2Fiknuz7j5yunc1owf93ci.jpeg" alt="Same Same" width="500" height="559"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  📋 The &lt;code&gt;.bumpversion.toml&lt;/code&gt; Glow-Up
&lt;/h2&gt;

&lt;p&gt;The config file now tracks &lt;strong&gt;all version-carrying files in the project&lt;/strong&gt;, not just &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[bumpversion]&lt;/span&gt;
&lt;span class="py"&gt;current_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:Cargo.toml]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:package.json]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:README.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:RUST.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:WASM.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:DOCKER.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;`{current_version}`&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;`{new_version}`&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:PACKAGING.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;current_version&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;new_version&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:rpm/bump2version.spec]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;Version:&lt;/span&gt; &lt;span class="err"&gt;{current_version}&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;Version:&lt;/span&gt; &lt;span class="err"&gt;{new_version}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One &lt;code&gt;bump --bump patch&lt;/code&gt; and every single version string, across docs, code, configs, packaging specs, and Docker manifests, updates atomically. The Mossad agents reviewed this config and said "acceptable" which, from them, is essentially a standing ovation.&lt;/p&gt;
&lt;h2&gt;
  
  
  🦀 The Borrow Checker Tried to Ruin Watch Mode
&lt;/h2&gt;

&lt;p&gt;There is a moment in every Rust developer's life, we all know the moment, where you look at a piece of code that &lt;em&gt;should&lt;/em&gt; work, that &lt;em&gt;does&lt;/em&gt; work in your head, that you have drawn on paper with arrows and boxes to prove its correctness, and the borrow checker looks at you across the compiler output and says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;error[E0505]: cannot move out of 'watcher' because it is borrowed&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then below that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;note: the borrow later used here&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then below &lt;em&gt;that&lt;/em&gt;, a footnote that reads &lt;code&gt;note: move occurs because...&lt;/code&gt; followed by a chain of reasoning so long it wraps around to the next terminal page.&lt;/p&gt;

&lt;p&gt;The Yew WASM integration did this to me for different reasons: &lt;code&gt;gix&lt;/code&gt; depends on Unix syscalls (&lt;code&gt;openat&lt;/code&gt;, &lt;code&gt;statx&lt;/code&gt;, platform symlink handling) that simply do not exist in &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt;. The linker error was 47 lines long and named three crates I had never heard of.&lt;/p&gt;

&lt;p&gt;The fix: gating all git-related functionality behind a &lt;code&gt;git&lt;/code&gt; feature flag that is disabled by default for WASM builds. Clean. Simple. The kind of solution that is obvious in retrospect and invisible before you spend four hours in the linker output.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[features]&lt;/span&gt;
&lt;span class="py"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;git&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"gix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;cli&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"clap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;rust-binary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"detect"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"watch"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c"&gt;# ← full featured binary&lt;/span&gt;
&lt;span class="py"&gt;watch&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"notify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cli"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;detect&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"walkdir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cli"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The WASM app uses none of the &lt;code&gt;git&lt;/code&gt; features. The CLI binary uses all of them. The feature graph is clean enough that my Mossad advisors called it "elegant" before immediately asking about the benchmark numbers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwqup7zmfsm21rjicnqk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmwqup7zmfsm21rjicnqk.gif" alt="Me excising gix." width="576" height="519"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  📦 Getting The Full Picture
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The complete CLI, with everything&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;bump2version &lt;span class="nt"&gt;--features&lt;/span&gt; rust-binary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This gets you &lt;code&gt;bump&lt;/code&gt;, &lt;code&gt;cargo-bump&lt;/code&gt;, and &lt;code&gt;bump2version&lt;/code&gt;. All 3. No choices required. Just install and bump.&lt;/p&gt;
&lt;h3&gt;
  
  
  Quick Examples
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Standard semver&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch           &lt;span class="c"&gt;# 0.2.1 → 0.2.2&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; minor           &lt;span class="c"&gt;# 0.2.1 → 0.3.0&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; major           &lt;span class="c"&gt;# 0.2.1 → 1.0.0&lt;/span&gt;

&lt;span class="c"&gt;# Safe preview&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; minor &lt;span class="nt"&gt;-n&lt;/span&gt;        &lt;span class="c"&gt;# same thing, shorter&lt;/span&gt;

&lt;span class="c"&gt;# Git integration&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--commit&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt;

&lt;span class="c"&gt;# Custom message&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; minor &lt;span class="nt"&gt;--commit&lt;/span&gt; &lt;span class="nt"&gt;--message&lt;/span&gt; &lt;span class="s2"&gt;"chore: ship {new_version} 🚀"&lt;/span&gt;

&lt;span class="c"&gt;# Auto-detect all manifests&lt;/span&gt;
bump &lt;span class="nt"&gt;--bump&lt;/span&gt; patch &lt;span class="nt"&gt;--detect&lt;/span&gt;

&lt;span class="c"&gt;# Watch mode (exits when you ctrl + c)&lt;/span&gt;
bump &lt;span class="nt"&gt;--watch&lt;/span&gt; &lt;span class="nt"&gt;--bump&lt;/span&gt; patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  As a library (no &lt;code&gt;std&lt;/code&gt; required for the core)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;bump2version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;default-features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&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 rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bump2version&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BumpConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;version&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;parse_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serialize_version&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BumpConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.2.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"minor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;serialize_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"1.3.0"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bump-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;bump_rs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bump_version&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2.3&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;major&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# "2.0.0" in ~57µs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Node.js
&lt;/h3&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;bump2version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bumpVersion&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bump2version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bumpVersion&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.2.3&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;patch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "1.2.4"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  🚀 What Comes After 1,000,000×
&lt;/h2&gt;

&lt;p&gt;Look, at some point the law of diminishing returns kicks in. We cannot make version bumping faster than the speed of light. (We checked. We asked the Mossad agents. They checked their slides. The answer was no.)&lt;/p&gt;

&lt;p&gt;But there are things we &lt;em&gt;can&lt;/em&gt; still do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-release cycling&lt;/strong&gt;: proper &lt;code&gt;alpha.1 → alpha.2 → beta.1 → rc.1 → stable&lt;/code&gt; lifecycle, first-class&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace-aware bumping&lt;/strong&gt;: atomic multi-crate Cargo workspace updates, all in one commit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More &lt;code&gt;detect&lt;/code&gt; targets&lt;/strong&gt;: &lt;code&gt;.NET&lt;/code&gt; (&lt;code&gt;*.csproj&lt;/code&gt;), PHP (&lt;code&gt;composer.json&lt;/code&gt;), Swift (&lt;code&gt;Package.swift&lt;/code&gt;), Elixir (&lt;code&gt;mix.exs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser version history&lt;/strong&gt;: the Yew app keeps a local bump history so you can see what you broke and when&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want any of these sooner: &lt;a href="https://github.com/wiseaidev/bump2version/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;. Or just star the repo and the moral pressure will accelerate delivery. It works on me. I've tested this empirically.&lt;/p&gt;
&lt;h2&gt;
  
  
  💬 Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bump2version 0.2.1&lt;/code&gt; started as a performance exercise and became an ecosystem. What was a single binary is now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Rust library&lt;/strong&gt; with &lt;code&gt;no_std&lt;/code&gt; support for the core&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Python package&lt;/strong&gt; (&lt;code&gt;bump-rs&lt;/code&gt;) for Pythonistas who want the speed without the syntax&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Node.js native add-on&lt;/strong&gt; for JavaScript developers who want to feel like they're using Rust&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;CLI&lt;/strong&gt; with three binary names: &lt;code&gt;bump&lt;/code&gt;, &lt;code&gt;cargo-bump&lt;/code&gt;, &lt;code&gt;bump2version&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;WASM browser app&lt;/strong&gt; built in Yew, because someone had to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 language examples&lt;/strong&gt; covering Rust, Python, Node.js, Go, Java, Ruby, and poly-repo workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20 integration tests&lt;/strong&gt; that test the actual binary, not a mock&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;auto-updatable &lt;code&gt;.bumpversion.toml&lt;/code&gt;&lt;/strong&gt; that tracks all version strings across the entire project&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;cargo install bump2version --features rust-binary&lt;/code&gt; → bump → ship → repeat → be 1,000,000× faster than Python → sleep → repeat 🦀&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/wiseaidev" rel="noopener noreferrer"&gt;
        wiseaidev
      &lt;/a&gt; / &lt;a href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;
        bump2version
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ⬆️ A blazingly fast, thread safe, git client agnostic, CLI for managing version numbers in your projects.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⬆️ Bump2version&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/wiseaidev/bump2version" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fbump2version%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="bump2version logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/802d34f5c2c10f09aacfd4317d833f9c3c9cfa812490590c063294d111f107fa/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f62756d703276657273696f6e2e737667" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://docs.rs/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/734cde23acd8b9ac2a0bf8d08e730c4c33cbaf5265b2bf6f8ff9ebdf329e24b4/68747470733a2f2f646f63732e72732f62756d703276657273696f6e2f62616467652e737667" alt="Docs.rs"&gt;&lt;/a&gt;
&lt;a href="https://pypi.org/project/bump-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4150a4da2ff10fc088be15aa56c9a153fe5151325f968237e698d05747cfc4cf/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f62756d702d72732e737667" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/22850addeaa5b9c3e7d7cc7e0a0d668623ac3bb887e0a5dc1341047a5294bef5/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f62756d703276657273696f6e2e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://hub.docker.com/r/wiseaidev/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eb74e4b93845037c4b78e54166dd900d3925222869991d17dac951068e566858/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f762f7769736561696465762f62756d703276657273696f6e3f6c6162656c3d646f636b6572" alt="Docker"&gt;&lt;/a&gt;
&lt;a href="https://github.com/marketplace/actions/bump-rs" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e3a947df13c81de37af5bac52c211f6113dfcf59408087872570814763ca4902/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61726b6574706c6163652d62756d703276657273696f6e2d626c75653f6c6f676f3d676974687562" alt="GitHub Marketplace"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/bump2version/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; is the world's fastest version bumper written entirely in &lt;strong&gt;100% safe Rust&lt;/strong&gt;, with &lt;code&gt;no_std&lt;/code&gt; support, native Python and Node.js bindings, and a &lt;code&gt;cargo bump&lt;/code&gt; subcommand 🗿.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/wiseaidev/bump2version" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fbump2version%2Frefs%2Fheads%2Fmain%2Fassets%2Fnew-banner.png" alt="bump2version banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust binary&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo install bump2version --features rust-binary&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cargo subcommand&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo bump --help&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker pull wiseaidev/bump2version&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debian/Ubuntu&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.deb&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RHEL/Fedora&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.rpm&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;bump.exe&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Action&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;See &lt;a href="https://github.com/wiseaidev/bump2version/blob/main/action.yml" rel="noopener noreferrer"&gt;action.yml&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install bump-rs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm install bump2version&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Installing via &lt;code&gt;cargo&lt;/code&gt; installs both &lt;code&gt;bump&lt;/code&gt; and &lt;code&gt;bump2version&lt;/code&gt; binaries. The original &lt;code&gt;bump2version&lt;/code&gt; binary is retained indefinitely for backward compatibility with existing tutorials, CI/CD pipelines, and automation scripts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 What does this crate provide?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; automates semantic version management for any project regardless of language. It:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parses&lt;/strong&gt; version strings using a fully configurable regex (default: semver &lt;code&gt;major.minor.patch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bumps&lt;/strong&gt; any named component (&lt;code&gt;major&lt;/code&gt;, &lt;code&gt;minor&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt;, or…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Star &lt;a href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;the repo&lt;/a&gt;. Try the &lt;a href="https://pypi.org/project/bump-rs" rel="noopener noreferrer"&gt;Python bindings&lt;/a&gt;. Use the &lt;a href="https://www.npmjs.com/package/bump2version" rel="noopener noreferrer"&gt;Node.js package&lt;/a&gt;. Read the &lt;a href="https://docs.rs/bump2version" rel="noopener noreferrer"&gt;Rust docs&lt;/a&gt;. Poke the &lt;a href="https://github.com/wiseaidev/bump2version/tree/main/examples/yew-app" rel="noopener noreferrer"&gt;WASM demo&lt;/a&gt;. Run the &lt;a href="https://github.com/wiseaidev/bump2version/tree/main/examples" rel="noopener noreferrer"&gt;examples&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This has been a public service announcement from a developer who, in the course of a single engineering session, created 20 tests, 7 example projects, a WASM frontend, a Soviet-themed benchmark suite, and consumed an amount of Claude tokens that my accountant has asked me not to disclose.&lt;/p&gt;

&lt;p&gt;The legal proceedings with Top Tech companies remain ongoing. My lawyer has read this post. He has asked me to note, for the record, that "abusing Claude" is a colloquial and affectionate term and not a legally actionable description of token consumption.&lt;/p&gt;

&lt;p&gt;I have not taken that advice either.&lt;/p&gt;

&lt;p&gt;Till next time: &lt;em&gt;Keep bumpin', keep rustin', keep benchmarkin'&lt;/em&gt; 🦀⬆️&lt;/p&gt;

&lt;p&gt;P.S. The Mossad agents have approved this post subject to the removal of the classified section about the branchless arithmetic lookup table. We kept it in. They know. They've said nothing. This is ominous.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Built a Version Bump Tool in Rust That Is 10,000x Faster Than Its Python Counterparts.</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sun, 06 Sep 2026 05:01:14 +0000</pubDate>
      <link>https://dev.to/wiseai/i-built-a-version-bump-tool-in-rust-that-is-10000x-faster-than-its-python-counterparts-i6b</link>
      <guid>https://dev.to/wiseai/i-built-a-version-bump-tool-in-rust-that-is-10000x-faster-than-its-python-counterparts-i6b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Hello, fellow version-bumping enthusiasts, sleep-deprived Rustaceans, and accidental software archaeologists who just found out that &lt;code&gt;bumpversion&lt;/code&gt; is a thing 👋!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there I was, staring at my terminal at 2AM, trying to release version &lt;code&gt;0.1.0&lt;/code&gt; of something. I typed &lt;code&gt;bump-my-version patch&lt;/code&gt;, pressed Enter, and watched my CPU fan spin up like it was launching a SpaceX rocket. One Second later, &lt;em&gt;one second&lt;/em&gt;, it bumped a number. One tiny number. &lt;code&gt;0.1.0&lt;/code&gt; → &lt;code&gt;0.1.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I sat there in silence for a moment.&lt;/p&gt;

&lt;p&gt;Then I did what any rational developer would do: I rewrote it. In Rust. From scratch. With Python &lt;em&gt;and&lt;/em&gt; Node.js bindings. And a CLI. And &lt;code&gt;no_std&lt;/code&gt; support. And &lt;code&gt;gix&lt;/code&gt; for pure-Rust git operations.&lt;/p&gt;

&lt;p&gt;The result? &lt;a href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;&lt;code&gt;bump2version&lt;/code&gt;&lt;/a&gt; &lt;code&gt;0.2.0&lt;/code&gt;: a version bumper that is legitimately, measurably, embarrassingly &lt;strong&gt;~10,000x faster&lt;/strong&gt; than the Python CLI it replaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvmpm05wtnz8d6w6gr5g2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvmpm05wtnz8d6w6gr5g2.webp" alt="Fast Ket Typing non stop!" width="250" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Wait, What Even Is &lt;code&gt;bump2version&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Glad you asked. &lt;code&gt;bump2version&lt;/code&gt; automates the tedious part of releasing software: updating version strings across multiple files. You know, the part where you manually grep through &lt;code&gt;Cargo.toml&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;CHANGELOG.md&lt;/code&gt;, and your README, change &lt;code&gt;1.2.3&lt;/code&gt; to &lt;code&gt;1.2.4&lt;/code&gt; in 11 different places, forget one, push, CI fails, and you cry quietly into your coffee?&lt;/p&gt;

&lt;p&gt;Yeah. That part.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; does all of that for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parses&lt;/strong&gt; version strings using a fully configurable regex (defaults to semver &lt;code&gt;major.minor.patch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bumps&lt;/strong&gt; any component you ask it to: &lt;code&gt;major&lt;/code&gt;, &lt;code&gt;minor&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt;, or custom cyclic stages like &lt;code&gt;alpha → beta → stable&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewrites&lt;/strong&gt; version occurrences across multiple files, including multiline &lt;code&gt;CHANGELOG&lt;/code&gt; patterns using proper &lt;code&gt;(?ms)&lt;/code&gt; DOTALL + MULTILINE semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commits and tags&lt;/strong&gt; via &lt;code&gt;gix&lt;/code&gt; - 100% pure-Rust git, zero subprocess calls, zero ghost authors in your commit history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it does all of this in &lt;strong&gt;safe Rust&lt;/strong&gt;, with &lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; at the crate root, because we have principles around here. Or at least we pretend to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# .bumpversion.toml: the config file that actually bumps the right things&lt;/span&gt;
&lt;span class="nn"&gt;[bumpversion]&lt;/span&gt;
&lt;span class="py"&gt;current_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;
&lt;span class="py"&gt;commit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;tag&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[bumpversion:file:Cargo.toml]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;'version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{current_version}"'&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;'version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{new_version}"'&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;span class="nn"&gt;[bumpversion:file:CHANGELOG.md]&lt;/span&gt;
&lt;span class="py"&gt;search&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"## {current_version}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    Release notes line 1"&lt;/span&gt;
&lt;span class="py"&gt;replace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"## {new_version}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;    Release notes line 1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One config file. Multiple files updated. One git commit. One tag. Done.&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%2Ftsobosjngwfbk4b4xm2x.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%2Ftsobosjngwfbk4b4xm2x.png" alt="2 GFs ain't enough bro!" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🦀 Rust, Python, and Node.js: A Love Triangle
&lt;/h2&gt;

&lt;p&gt;Here's the fun part: &lt;code&gt;bump2version&lt;/code&gt; isn't &lt;em&gt;just&lt;/em&gt; a Rust crate. It's three tools pretending to be one in a trench coat.&lt;/p&gt;
&lt;h3&gt;
  
  
  As a Rust crate:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;bump2version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bump2version&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;config&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BumpConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;version&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;parse_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serialize_version&lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BumpConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1.2.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;serialize_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 1.2.4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  As a Python package:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bump-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;bump_rs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BumpConfig&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2.3&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;patch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# "1.2.4"
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2.3&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;minor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# "1.3.0"
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.2.3&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;major&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# "2.0.0"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  As a Node.js add-on:
&lt;/h3&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;bump2version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;bumpVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyFileChange&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bump2version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bumpVersion&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.2.3&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;patch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// '1.2.4'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bumpVersion&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.2.3&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;minor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// '1.3.0'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One Rust core. Three ecosystems. Zero Python subprocesses. Ferris the crab is now a polyglot, and honestly? Good for them. 🦀&lt;/p&gt;
&lt;h2&gt;
  
  
  🕵️ The Mossad Agents Who Architected This
&lt;/h2&gt;

&lt;p&gt;Let me be transparent about one thing: I did not architect the full system design for this project alone.&lt;/p&gt;

&lt;p&gt;No, I had help. Specifically, I reached out to some very professional consultants.&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%2Fh7ehyj77nggirkaj2gdb.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%2Fh7ehyj77nggirkaj2gdb.png" alt="The Mossad Agents That Helped Me Develop This Project." width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;They arrived at my door at 3AM with a whiteboard and a very detailed opinion on &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; caching strategies.&lt;/em&gt; Their key architectural recommendation, which I followed verbatim after reviewing it at gunpoint (metaphorically, probably), was the thread-safe &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; cache. This means the compiled regex pattern is compiled &lt;em&gt;once&lt;/em&gt;, shared across threads, and reused for every subsequent call, no recompilation overhead on hot paths.&lt;/p&gt;

&lt;p&gt;The result: version bumping in &lt;strong&gt;~57 microseconds&lt;/strong&gt; from Python land. Not 57 milliseconds. Not 57 seconds. &lt;strong&gt;57 microseconds.&lt;/strong&gt; The kind of number that makes you wonder what the Python version was doing during its 585 millisecond run.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔥 The Numbers That Made Me Cackle Maniacally
&lt;/h2&gt;

&lt;p&gt;Okay. Let's talk benchmarks. Because this is the part of the blog post where I get to paste a table and feel deeply smug about it.&lt;/p&gt;

&lt;p&gt;These are real numbers, measured on x86-64 Linux (CPython 3.12, 3-sigma filtered &lt;code&gt;timeit&lt;/code&gt;):&lt;/p&gt;
&lt;h3&gt;
  
  
  Version Bumping: Full Round-Trip (Parse + Bump + Serialize)
&lt;/h3&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;&lt;code&gt;patch&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;minor&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;major&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;bump-rs&lt;/strong&gt; (Rust, &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; cache)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~57 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~54 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~53 µs&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;bump-my-version&lt;/code&gt; (Python library)&lt;/td&gt;
&lt;td&gt;~79 µs&lt;/td&gt;
&lt;td&gt;~95 µs&lt;/td&gt;
&lt;td&gt;~72 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure Python (&lt;code&gt;re.compile&lt;/code&gt; + &lt;code&gt;int()&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;~3.6 µs&lt;/td&gt;
&lt;td&gt;~2.2 µs&lt;/td&gt;
&lt;td&gt;~2.2 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;bump-my-version&lt;/code&gt; CLI (subprocess)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~585 ms&lt;/td&gt;
&lt;td&gt;~585 ms&lt;/td&gt;
&lt;td&gt;~585 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The headline result: &lt;strong&gt;bump-rs is ~10,000× faster than the &lt;code&gt;bump-my-version&lt;/code&gt; CLI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, I can already hear you: &lt;em&gt;"But the pure Python version is actually faster for single calls!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes. You're right. The ~50 µs PyO3 FFI overhead means that if you're bumping exactly one version string in isolation on a warm Python interpreter, pure &lt;code&gt;re.compile&lt;/code&gt; + &lt;code&gt;int()&lt;/code&gt; will smoke us.&lt;/p&gt;

&lt;p&gt;But the moment you're doing anything real, parsing a config file, updating multiple files, running a git commit, you're doing it once with &lt;code&gt;bump-rs&lt;/code&gt; vs. spawning a subprocess, importing &lt;code&gt;click&lt;/code&gt;, importing &lt;code&gt;importlib&lt;/code&gt;, importing the entire &lt;code&gt;bump-my-version&lt;/code&gt; dependency graph... and waiting &lt;strong&gt;585 milliseconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every. Single. Time.&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%2Fqqmj23akymoxqd6zhuz9.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%2Fqqmj23akymoxqd6zhuz9.png" alt="Why would you do this, ma boy!" width="800" height="633"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  File Search/Replace
&lt;/h3&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;Single-line&lt;/th&gt;
&lt;th&gt;Multiline CHANGELOG&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;bump-rs&lt;/strong&gt; (Rust, cached)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~65 µs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~104 µs&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure Python &lt;code&gt;re.sub&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;~1.7 µs&lt;/td&gt;
&lt;td&gt;~1.3 µs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For file I/O work, thread safety, and pipeline operations, bump-rs wins. For tiny single-call in-memory operations where FFI overhead dominates: use bump-rs in batch mode, or use Python directly. We believe in honesty here.&lt;/p&gt;
&lt;h2&gt;
  
  
  🤖 Abusing Claude to Achieve the 10,000x Speed-Up
&lt;/h2&gt;

&lt;p&gt;Here's a confession. A &lt;em&gt;deeply personal&lt;/em&gt; one. One that my legal team has strongly advised me not to make public.&lt;/p&gt;

&lt;p&gt;I abused Claude.&lt;/p&gt;

&lt;p&gt;Not in the &lt;em&gt;normal&lt;/em&gt; way where you ask it to generate boilerplate. No no no. I pushed it to its absolute limits. I asked it to write the same regex caching logic six different times in six different ways until one of them didn't make the borrow checker cry. I had it architecting FFI boundary semantics at 4AM. I used it to debate whether &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; was overkill for a single-threaded benchmark (it was not). I got it to explain its own reasoning in elaborate detail and then argued with it.&lt;/p&gt;

&lt;p&gt;Anthropic noticed.&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%2F2g8ab84qeb8my3ovog5m.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%2F2g8ab84qeb8my3ovog5m.png" alt="My lawyer defending me in court for abusing Claude" width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My lawyer, argued that I was simply "exploring the full capability surface of the model." The judge was unmoved. The Anthropic lawyers were also unmoved, but in a different direction.&lt;/p&gt;

&lt;p&gt;The verdict is still pending. The &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; cache, however, is production-ready.&lt;/p&gt;

&lt;p&gt;The lesson here: if you want to squeeze 10,000x performance out of a tool, you need to be willing to go to uncomfortable places. Dark places. Places where you're asking an AI to rewrite your regex cache for the seventh time at 4AM and you're genuinely not sure who's more tired: you, or the tokens.&lt;/p&gt;

&lt;p&gt;Turns out: the tokens don't get tired. That's why Rust wins.&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%2Fdazc134i4fcjglk489yo.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%2Fdazc134i4fcjglk489yo.png" alt="Argue with Claude about the regex caching strategy!" width="799" height="505"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🐴 And Then the Borrow Checker Got Stuck
&lt;/h2&gt;

&lt;p&gt;There is a moment in every Rust developer's life where you write something that you &lt;em&gt;know&lt;/em&gt; is correct, you've proven it in your head using mathematical induction and also vibes, and the borrow checker looks you dead in the eyes and says: &lt;strong&gt;"No."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No explanation. No suggestion. Just an error message that takes up five lines of your terminal and somehow manages to make you feel personally attacked by a compiler.&lt;/p&gt;

&lt;p&gt;That happened. Multiple times. Specifically in the Python binding layer, where the intersection of PyO3's GIL management, &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; shared state, and Rust's lifetime rules creates a special kind of chaos that can only be described as "my head hurts and I want to go home".&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%2Frn1u2hlbr7pvblg2n2vg.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%2Frn1u2hlbr7pvblg2n2vg.png" alt="AND My Rust Borrow Checker Got Stuck!" width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The horse on the balcony railing is an accurate representation of &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;HashMap&amp;lt;String, Regex&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; trying to cross a PyO3 function boundary. It got there. It works. But the &lt;code&gt;stuck&lt;/code&gt; moment before it worked? That was real.&lt;/p&gt;

&lt;p&gt;The fix, anticlimactically, was changing the cache from a &lt;code&gt;HashMap&lt;/code&gt; behind a &lt;code&gt;Mutex&lt;/code&gt; to a thread-local &lt;code&gt;Arc&amp;lt;Regex&amp;gt;&lt;/code&gt; initialized with &lt;code&gt;once_cell::sync::Lazy&lt;/code&gt;. The borrow checker immediately, &lt;em&gt;graciously&lt;/em&gt;, let the horse off the railing.&lt;/p&gt;

&lt;p&gt;There's a metaphor in there somewhere. I choose not to examine it too closely.&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%2Ffusdnnqfpoewyvul7glq.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%2Ffusdnnqfpoewyvul7glq.png" alt="There's a metaphor in there somewhere." width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠️ Getting Started
&lt;/h2&gt;

&lt;p&gt;Let's get practical. Here's how to use &lt;code&gt;bump2version&lt;/code&gt; in your project right now:&lt;/p&gt;
&lt;h3&gt;
  
  
  CLI Usage
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;bump2version &lt;span class="nt"&gt;--features&lt;/span&gt; rust-binary

bump2version &lt;span class="nt"&gt;--bump&lt;/span&gt; patch   &lt;span class="c"&gt;# 0.2.0 → 0.2.1&lt;/span&gt;
bump2version &lt;span class="nt"&gt;--bump&lt;/span&gt; minor   &lt;span class="c"&gt;# 0.2.0 → 0.3.0&lt;/span&gt;
bump2version &lt;span class="nt"&gt;--bump&lt;/span&gt; major   &lt;span class="c"&gt;# 0.2.0 → 1.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Useful flags:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--config-file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specify config file path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--current-version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Override detected current version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--bump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which part: &lt;code&gt;major&lt;/code&gt;, &lt;code&gt;minor&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--dry-run&lt;/code&gt; / &lt;code&gt;-n&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Simulate without touching any file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--commit&lt;/code&gt; / &lt;code&gt;--tag&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Auto-commit and tag after bumping&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bump-rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;bump_rs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apply_file_change&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BumpConfig&lt;/span&gt;

&lt;span class="c1"&gt;# Custom parse/serialize for 2-component versions
&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BumpConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?P&amp;lt;major&amp;gt;\d+)\.(?P&amp;lt;minor&amp;gt;\d+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{major}.{minor}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bump_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.0&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;minor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# "2.1"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Node.js
&lt;/h3&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;bump2version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;bumpVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;applyFileChange&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;bump2version&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;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bumpVersion&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.2.3&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;minor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "1.3.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;no_std&lt;/code&gt; Embedding
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;bump2version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;default-features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The core modules (&lt;code&gt;config&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;, &lt;code&gt;files&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;) compile on &lt;code&gt;no_std + alloc&lt;/code&gt;. Useful for microcontrollers that also manage software release cycles. You know. If that's your situation.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔒 The Safety Contract
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; enforces &lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; at the crate root. Every byte of the implementation, config parsing, regex matching, version bumping, git object creation, is written in safe Rust. The compiler will literally &lt;em&gt;reject&lt;/em&gt; any future &lt;code&gt;unsafe&lt;/code&gt; introduced into the safe portions.&lt;/p&gt;

&lt;p&gt;The only &lt;code&gt;unsafe&lt;/code&gt; in the entire codebase is in the Node.js FFI layer, because &lt;code&gt;napi-rs&lt;/code&gt; requires it for native add-on interop and there's genuinely no way around that. If we could have avoided it, we would have. We tried. The borrow checker nodded approvingly at our effort, then still said no.&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%2F2s0kqjh7eqfsuvsf2hy7.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%2F2s0kqjh7eqfsuvsf2hy7.png" alt="unsafe Rust in production" width="741" height="734"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🔭 What's Coming in Future Releases
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; 0.2.0 is out the door, but the roadmap is full:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspace-aware bumping&lt;/strong&gt;: Update all crates in a Cargo workspace atomically in a single pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-release cycling&lt;/strong&gt;: Better first-class support for &lt;code&gt;alpha → beta → rc → stable&lt;/code&gt; lifecycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch mode&lt;/strong&gt;: Because apparently some people want their versions bumped on file save. (I won't judge. I &lt;em&gt;want&lt;/em&gt; to judge, but I won't.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WASM target&lt;/strong&gt;: Core logic compiled to WebAssembly for browser-side version management. Yes, this is probably overkill. Yes, we're doing it anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More benchmarks&lt;/strong&gt;: The Mossad agents have requested a full comparative analysis against every Python version tool ever created. We've filed the paperwork.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Look. At the end of the day, &lt;code&gt;bump2version&lt;/code&gt; does one thing: it bumps numbers in your files, commits the result, and tags the commit. That's it. That's the whole feature set.&lt;/p&gt;

&lt;p&gt;But it does it in &lt;strong&gt;safe Rust&lt;/strong&gt;. With &lt;strong&gt;Python bindings&lt;/strong&gt; so Pythonistas don't have to care. With &lt;strong&gt;Node.js bindings&lt;/strong&gt; so JavaScript developers can pretend they're also using Rust. With &lt;strong&gt;no_std support&lt;/strong&gt; so embedded engineers can participate in the versioning conversation. With &lt;strong&gt;pure-gix git integration&lt;/strong&gt; so there are zero subprocess calls anywhere in the hot path. And with benchmarks that show it's &lt;strong&gt;~10,000x faster&lt;/strong&gt; than the incumbent CLI tool.&lt;/p&gt;

&lt;p&gt;Is that overkill for bumping a number? Absolutely. Are we sorry? Not even slightly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;cargo install bump2version --features rust-binary&lt;/code&gt; → bump → ship → repeat 🦀&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Star &lt;a href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;the repo&lt;/a&gt;, try the &lt;a href="https://pypi.org/project/bump-rs" rel="noopener noreferrer"&gt;Python bindings&lt;/a&gt;, install the &lt;a href="https://www.npmjs.com/package/bump2version" rel="noopener noreferrer"&gt;npm package&lt;/a&gt;, or just read the &lt;a href="https://docs.rs/bump2version" rel="noopener noreferrer"&gt;docs&lt;/a&gt;. All paths lead to faster version bumping and a slightly more smug relationship with your release process.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/wiseaidev" rel="noopener noreferrer"&gt;
        wiseaidev
      &lt;/a&gt; / &lt;a href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;
        bump2version
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ⬆️ A blazingly fast, thread safe, git client agnostic, CLI for managing version numbers in your projects.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;⬆️ Bump2version&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/wiseaidev/bump2version" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fbump2version%2Frefs%2Fheads%2Fmain%2Fassets%2Flogo.png" alt="bump2version logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://crates.io/crates/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/802d34f5c2c10f09aacfd4317d833f9c3c9cfa812490590c063294d111f107fa/68747470733a2f2f696d672e736869656c64732e696f2f6372617465732f762f62756d703276657273696f6e2e737667" alt="Crates.io"&gt;&lt;/a&gt;
&lt;a href="https://docs.rs/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/734cde23acd8b9ac2a0bf8d08e730c4c33cbaf5265b2bf6f8ff9ebdf329e24b4/68747470733a2f2f646f63732e72732f62756d703276657273696f6e2f62616467652e737667" alt="Docs.rs"&gt;&lt;/a&gt;
&lt;a href="https://pypi.org/project/bump-rs" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4150a4da2ff10fc088be15aa56c9a153fe5151325f968237e698d05747cfc4cf/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f62756d702d72732e737667" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/22850addeaa5b9c3e7d7cc7e0a0d668623ac3bb887e0a5dc1341047a5294bef5/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f62756d703276657273696f6e2e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://hub.docker.com/r/wiseaidev/bump2version" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eb74e4b93845037c4b78e54166dd900d3925222869991d17dac951068e566858/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f762f7769736561696465762f62756d703276657273696f6e3f6c6162656c3d646f636b6572" alt="Docker"&gt;&lt;/a&gt;
&lt;a href="https://github.com/marketplace/actions/bump-rs" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e3a947df13c81de37af5bac52c211f6113dfcf59408087872570814763ca4902/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d61726b6574706c6163652d62756d703276657273696f6e2d626c75653f6c6f676f3d676974687562" alt="GitHub Marketplace"&gt;&lt;/a&gt;
&lt;a href="https://github.com/wiseaidev/bump2version/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; is the world's fastest version bumper written entirely in &lt;strong&gt;100% safe Rust&lt;/strong&gt;, with &lt;code&gt;no_std&lt;/code&gt; support, native Python and Node.js bindings, and a &lt;code&gt;cargo bump&lt;/code&gt; subcommand 🗿.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/wiseaidev/bump2version" 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%2Fraw.githubusercontent.com%2Fwiseaidev%2Fbump2version%2Frefs%2Fheads%2Fmain%2Fassets%2Fnew-banner.png" alt="bump2version banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust binary&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo install bump2version --features rust-binary&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cargo subcommand&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cargo bump --help&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker pull wiseaidev/bump2version&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debian/Ubuntu&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.deb&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RHEL/Fedora&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;.rpm&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Download &lt;code&gt;bump.exe&lt;/code&gt; from &lt;a href="https://github.com/wiseaidev/bump2version/releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Action&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;See &lt;a href="https://github.com/wiseaidev/bump2version/blob/main/action.yml" rel="noopener noreferrer"&gt;action.yml&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pip install bump-rs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm install bump2version&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Installing via &lt;code&gt;cargo&lt;/code&gt; installs both &lt;code&gt;bump&lt;/code&gt; and &lt;code&gt;bump2version&lt;/code&gt; binaries. The original &lt;code&gt;bump2version&lt;/code&gt; binary is retained indefinitely for backward compatibility with existing tutorials, CI/CD pipelines, and automation scripts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤔 What does this crate provide?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;bump2version&lt;/code&gt; automates semantic version management for any project regardless of language. It:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parses&lt;/strong&gt; version strings using a fully configurable regex (default: semver &lt;code&gt;major.minor.patch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bumps&lt;/strong&gt; any named component (&lt;code&gt;major&lt;/code&gt;, &lt;code&gt;minor&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt;, or…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/wiseaidev/bump2version" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This has been a public service announcement from a developer who really, &lt;em&gt;really&lt;/em&gt; did not want to wait 585 milliseconds for a number to go up by one.&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%2Fsqtbkyw9vkti054mq6pq.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%2Fsqtbkyw9vkti054mq6pq.png" alt="pip install bump-rs" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Till next time: &lt;em&gt;Keep bumpin', keep rustin'&lt;/em&gt; 🦀⬆️&lt;/p&gt;

&lt;p&gt;P.S. The legal proceedings with Anthropic are ongoing. My lawyer has advised me to stop mentioning it. I have not taken that advice.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🏳️‍🌈 Pride RS 0.1.0: Dropping the T from LGBTQ+ &amp; Mark It as Haram.</title>
      <dc:creator>Mahmoud 🦀</dc:creator>
      <pubDate>Sat, 29 Aug 2026 07:37:59 +0000</pubDate>
      <link>https://dev.to/wiseai/pride-rs-010-dropping-the-t-from-lgbtq-mark-it-as-haram-1508</link>
      <guid>https://dev.to/wiseai/pride-rs-010-dropping-the-t-from-lgbtq-mark-it-as-haram-1508</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Welcome back 👋, brave soul!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, &lt;a href="https://github.com/opensass/pride-rs/releases/tag/v0.0.2" rel="noopener noreferrer"&gt;version 0.0.2 of &lt;strong&gt;Pride RS&lt;/strong&gt;&lt;/a&gt; barely had time to dry before the community showed up in the Discord with... &lt;em&gt;opinions&lt;/em&gt;. Big ones. Ferris the crab 🦀 got some letters. The Open SASS council convened. Arguments were had. And after a very long, very heated, very productive engineering debate (mostly in memes), &lt;strong&gt;Pride RS 0.1.0&lt;/strong&gt; is here.&lt;/p&gt;

&lt;p&gt;The headline? &lt;strong&gt;We're dropping the T from LGBTQ+, and shipping it as a Cargo feature gate called &lt;code&gt;haram&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before you type in that issue, yes, you can still opt-in. It's Rust. Everything is opt-in. That's kind of the whole point. 😌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffl74jjvsw8s91nxvtz7p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffl74jjvsw8s91nxvtz7p.gif" alt="Ferris the crab slowly backing away from a gender studies textbook" width="480" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 What Even Is &lt;code&gt;haram&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;In Arabic, &lt;em&gt;haram&lt;/em&gt; (حرام) means "forbidden". In &lt;strong&gt;Pride RS&lt;/strong&gt;, it means: &lt;em&gt;"these flag types are guarded behind a feature gate and won't compile unless you explicitly ask for them."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Specifically, the following four flag types are now gated:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What it represents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Transgender&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Gender transition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NonBinary&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Non-binary gender identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Genderfluid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fluid gender identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Agender&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Absence of gender identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These four have one thing in common: they're all about &lt;strong&gt;changing or rejecting biological gender&lt;/strong&gt;, which, in the Ferris cosmos, is debatably haram. The crab has spoken. Or at least, the Cargo feature flag has.&lt;/p&gt;

&lt;p&gt;The other eleven types, Rainbow, Bisexual, Lesbian, Pansexual, Asexual, Aromantic, Demisexual, Polysexual, Omnisexual, Demiromantic, Graysexual, remain fully available with no feature flag required. Those are the &lt;strong&gt;halal&lt;/strong&gt; ones. Rainbow stays. Obviously. Ferris loves rainbows.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  ⚙️ Under the Hood
&lt;/h2&gt;

&lt;p&gt;You'd think adding a Cargo feature gate is simple. You'd be wrong. Here's why:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.rs/phf" rel="noopener noreferrer"&gt;&lt;code&gt;phf&lt;/code&gt;&lt;/a&gt;, our compile-time perfect hash map, does &lt;strong&gt;not&lt;/strong&gt; support &lt;code&gt;#[cfg(...)]&lt;/code&gt; inside a single &lt;code&gt;phf_map!&lt;/code&gt; invocation. You can't do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;FLAG_CONFIGURATIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;phf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;phf_map!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"Rainbow"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&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="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;-- NOPE. Compiler says no.&lt;/span&gt;
    &lt;span class="s"&gt;"Transgender"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So instead, we compile &lt;strong&gt;two entirely separate maps&lt;/strong&gt;, gated by &lt;code&gt;#[cfg]&lt;/code&gt; at the item level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(not(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;FLAG_CONFIGURATIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;phf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;phf_map!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 11 halal entries&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;FLAG_CONFIGURATIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;phf&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;phf_map!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 15 entries (all flags)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two statics. Same name. Mutually exclusive. Zero runtime overhead. &lt;strong&gt;Perfectly legal Rust.&lt;/strong&gt; Ferris approves. 🦀✅&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%2Fe48lbq8v8bgwjzszrg7s.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%2Fe48lbq8v8bgwjzszrg7s.png" alt="Two identical doors" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚩 The New &lt;code&gt;Type&lt;/code&gt; Enum
&lt;/h2&gt;

&lt;p&gt;Here's what &lt;code&gt;Type&lt;/code&gt; looks like now, straight from the codebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Rainbow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Bisexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Lesbian&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Pansexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Asexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Aromantic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Demisexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Polysexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Omnisexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Demiromantic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Graysexual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;Transgender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;NonBinary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;Genderfluid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;Agender&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;Without &lt;code&gt;--features haram&lt;/code&gt;, the four guarded variants don't exist. At all. Not a dead code warning. Not a &lt;code&gt;None&lt;/code&gt;. They literally &lt;strong&gt;do not compile into the binary&lt;/strong&gt;. Zero bytes. Zero overhead. Four fewer existential crises in your type system.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🔍 The &lt;code&gt;is_haram()&lt;/code&gt; Method
&lt;/h2&gt;

&lt;p&gt;New in 0.1.0, we ship a runtime inspection method, available only when the &lt;code&gt;haram&lt;/code&gt; feature is enabled (because, well, the variants don't even exist otherwise):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_haram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;matches!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transgender&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NonBinary&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Genderfluid&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Agender&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;O(1). No heap. No drama. Just a match arm and a boolean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transgender&lt;/span&gt;&lt;span class="nf"&gt;.is_haram&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rainbow&lt;/span&gt;&lt;span class="nf"&gt;.is_haram&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ferris the crab, checking IDs at the door like a bouncer in a tiny crab hat. 🦀🎩&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🏷️ The &lt;code&gt;haram&lt;/code&gt; Field on &lt;code&gt;FlagConfig&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We also added a &lt;code&gt;haram: bool&lt;/code&gt; field to the &lt;code&gt;FlagConfig&lt;/code&gt; struct itself, so that tooling, docs generators, and runtime inspectors can ask &lt;em&gt;"hey, is this flag type on the haram list?"&lt;/em&gt; without needing &lt;code&gt;#[cfg]&lt;/code&gt; gymnastics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;FlagConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;haram&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;-- new!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rainbow? &lt;code&gt;haram: false&lt;/code&gt;. Transgender (when enabled)? &lt;code&gt;haram: true&lt;/code&gt;. Useful if you want to render a little ⚠️ badge or log a warning before someone deploys a fully featured pride flag to a government app in Riyadh.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Using the &lt;code&gt;haram&lt;/code&gt; Feature
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Default (Halal) Edition
&lt;/h3&gt;

&lt;p&gt;Nothing changes. Just use Pride RS as before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;pride-rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"yew"&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;You get 11 flags. Go wild. Ferris blesses you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Edition (The &lt;code&gt;haram&lt;/code&gt; Opt-in)
&lt;/h3&gt;

&lt;p&gt;Add the feature flag to unlock all 15 types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;pride-rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"yew"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"haram"&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;Now the full quartet is available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;pride_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FlagSection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;pride_rs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FlagSection&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"questionable-choices"&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"The Haram Four"&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transgender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NonBinary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Genderfluid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Agender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No judgment. Cargo features are additive. Ship what you need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qpzrevknw58m0z2kn6y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qpzrevknw58m0z2kn6y.gif" alt="Person sneaking through a door labeled " width="220" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Tests: Now Cfg-Conditional
&lt;/h2&gt;

&lt;p&gt;The test suite was updated to reflect the new reality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_enum_iter_default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;#[cfg(not(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variants&lt;/span&gt;&lt;span class="nf"&gt;.len&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="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;variants&lt;/span&gt;&lt;span class="nf"&gt;.len&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a full &lt;code&gt;haram_tests&lt;/code&gt; module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"haram"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;haram_tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_is_haram_true_for_transgender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transgender&lt;/span&gt;&lt;span class="nf"&gt;.is_haram&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ... and more&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the halal suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the full suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--features&lt;/span&gt; haram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📦 0.1.0 Changelog Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✨ New feature gate&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;haram&lt;/code&gt;, compile-time toggle for gender-identity flags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🚩 New &lt;code&gt;Type&lt;/code&gt; variants gated&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Transgender&lt;/code&gt;, &lt;code&gt;NonBinary&lt;/code&gt;, &lt;code&gt;Genderfluid&lt;/code&gt;, &lt;code&gt;Agender&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔍 New method&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Type::is_haram()&lt;/code&gt; (available with &lt;code&gt;haram&lt;/code&gt; feature)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🏷️ New struct field&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FlagConfig::haram: bool&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📖 Docs&lt;/td&gt;
&lt;td&gt;Full rustdoc on every public item with time/space complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧪 Tests&lt;/td&gt;
&lt;td&gt;Cfg-conditional variant counts, full &lt;code&gt;haram_tests&lt;/code&gt; module&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 License&lt;/td&gt;
&lt;td&gt;MIT license banner on all source files&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Look, we're not here to debate theology or gender theory. We're here to write &lt;strong&gt;fast, correct, zero-overhead Rust&lt;/strong&gt;. And with 0.1.0, whether you want all 15 flags or just the 11 that Ferris's grandma would approve of, you get &lt;strong&gt;compile-time guarantees&lt;/strong&gt; either way.&lt;/p&gt;

&lt;p&gt;That's the Rust way. Strong types. Explicit opt-ins. No runtime surprises.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Zero overhead when &lt;code&gt;haram&lt;/code&gt; is off (variants don't exist in the binary)&lt;/li&gt;
&lt;li&gt;✅ Full access when &lt;code&gt;haram&lt;/code&gt; is on (explicit opt-in)&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;is_haram()&lt;/code&gt; for runtime inspection&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;FlagConfig::haram&lt;/code&gt; for tooling&lt;/li&gt;
&lt;li&gt;✅ Ferris the crab, canonically confuzled 🦀❓&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5lgggvoq6x88xtk7tmy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5lgggvoq6x88xtk7tmy.gif" alt="Confused crab" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compile it. Gate it. Ship it. Let the borrow checker sort it out 🏳️‍🌈🦀.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as always, if you have thoughts, flags (the physical kind OR the code kind), or strong opinions about Cargo feature semantics, swing by &lt;a href="https://discord.gg/b5JbvHW5nv" rel="noopener noreferrer"&gt;our Discord&lt;/a&gt;. Ferris is there. He's a little confused but he's trying his best.&lt;/p&gt;

&lt;p&gt;Till next time: &lt;em&gt;Keep Rustin', stay halal.&lt;/em&gt; 🦀💚&lt;/p&gt;

</description>
      <category>devpride</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
