<?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: Jonatas Sas</title>
    <description>The latest articles on DEV Community by Jonatas Sas (@jonatas-sas).</description>
    <link>https://dev.to/jonatas-sas</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2711719%2F2552c9dd-1f1c-4845-9624-d4e2231f9bf3.png</url>
      <title>DEV Community: Jonatas Sas</title>
      <link>https://dev.to/jonatas-sas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonatas-sas"/>
    <language>en</language>
    <item>
      <title>Inline AI Suggestions in NeoVim: GitHub Copilot vs Windsurf (Codeium) — A Technical Comparative Analysis</title>
      <dc:creator>Jonatas Sas</dc:creator>
      <pubDate>Tue, 06 May 2025 20:55:20 +0000</pubDate>
      <link>https://dev.to/jonatas-sas/inline-ai-suggestions-in-neovim-github-copilot-vs-windsurf-codeium-a-technical-comparative-4b7l</link>
      <guid>https://dev.to/jonatas-sas/inline-ai-suggestions-in-neovim-github-copilot-vs-windsurf-codeium-a-technical-comparative-4b7l</guid>
      <description>&lt;p&gt;Before we dive in, it's worth noting a recent branding change: the assistant formerly known as &lt;strong&gt;Codeium&lt;/strong&gt; is now called &lt;strong&gt;Windsurf&lt;/strong&gt;. The rebranding aims to reposition the tool under a new identity, though the transition has caused some confusion in the community, particularly among terminal-centric users. For clarity, throughout this article, we will refer to the tool as &lt;strong&gt;Windsurf&lt;/strong&gt;, its current official name.&lt;/p&gt;

&lt;p&gt;Among terminal enthusiasts, NeoVim has established itself as a powerhouse of productivity. Combining lightness, extensibility, and full control over the development environment, it's become the go-to editor for developers who not only write code but carefully curate a streamlined workflow. In this context, the integration of artificial intelligence tools for real-time code suggestions—commonly referred to as &lt;em&gt;inline suggestions&lt;/em&gt; — represents a significant and potentially transformative addition.&lt;/p&gt;

&lt;p&gt;In recent years, two major players have emerged in this space: &lt;strong&gt;GitHub Copilot&lt;/strong&gt;, developed in partnership with OpenAI and backed by the GitHub ecosystem, and &lt;strong&gt;Windsurf&lt;/strong&gt;, a free and increasingly popular alternative. Both aim to enhance developer productivity by anticipating and completing code based on context. But how do they actually perform within NeoVim—a notoriously demanding environment when it comes to customization and efficiency?&lt;/p&gt;

&lt;p&gt;This article offers a deep technical comparison focused specifically on how these tools behave in NeoVim. I will cover configuration, technical capabilities, plugin integration, LSP behavior, privacy, community adoption, and contextual awareness. The goal? To help you make an informed decision about which AI assistant to rely on in your daily workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup and Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Copilot (with enhanced integration)
&lt;/h3&gt;

&lt;p&gt;While the official &lt;code&gt;copilot.vim&lt;/code&gt; plugin is still available, it's highly recommended to use the modern &lt;code&gt;copilot.lua&lt;/code&gt; implementation paired with &lt;code&gt;copilot-cmp&lt;/code&gt;. This setup provides better control, full &lt;code&gt;nvim-cmp&lt;/code&gt; integration, and increased stability. Here's a recommended configuration using &lt;code&gt;lazy.nvim&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"zbirenbaum/copilot.lua"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Copilot"&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="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"copilot"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
  &lt;span class="k"&gt;end&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="s2"&gt;"zbirenbaum/copilot-cmp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"zbirenbaum/copilot.lua"&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="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"copilot_cmp"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&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 setup disables visual panels and enables suggestions exclusively through &lt;code&gt;nvim-cmp&lt;/code&gt;. Authentication is triggered via the &lt;code&gt;:Copilot auth&lt;/code&gt; command, which opens your browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why choose &lt;code&gt;copilot.lua&lt;/code&gt; over &lt;code&gt;copilot.vim&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native integration with &lt;code&gt;nvim-cmp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fine-grained control over appearance and behavior&lt;/li&gt;
&lt;li&gt;Better performance in asynchronous environments&lt;/li&gt;
&lt;li&gt;Community-maintained extensions like &lt;code&gt;copilot-lualine&lt;/code&gt; for status display&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Windsurf
&lt;/h3&gt;

&lt;p&gt;Windsurf’s installation process is equally simple and well-documented. Here is a basic configuration using &lt;code&gt;lazy.nvim&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"Exafunction/windsurf.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"nvim-lua/plenary.nvim"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"hrsh7th/nvim-cmp"&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="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"codeium"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
  &lt;span class="k"&gt;end&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;Once installed, use &lt;code&gt;:Codeium Auth&lt;/code&gt; to authenticate via the browser. The plugin integrates automatically with &lt;code&gt;nvim-cmp&lt;/code&gt; and requires Node.js on your system to function properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugin Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Copilot
&lt;/h3&gt;

&lt;p&gt;Copilot benefits from strong community support. With &lt;code&gt;copilot-cmp&lt;/code&gt;, it integrates directly with &lt;code&gt;nvim-cmp&lt;/code&gt; for inline completions. The &lt;code&gt;copilot-lualine&lt;/code&gt; plugin allows users to monitor the plugin's status in the statusline.&lt;/p&gt;

&lt;p&gt;Advanced users can extend functionality using &lt;code&gt;telescope.nvim&lt;/code&gt; to inspect logs and command history, or integrate &lt;code&gt;which-key.nvim&lt;/code&gt; for quick keymap discovery. Behavior can be further customized via commands and configuration hooks, especially when using &lt;code&gt;copilot.lua&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windsurf
&lt;/h3&gt;

&lt;p&gt;Windsurf provides solid integration with essential tools like &lt;code&gt;nvim-cmp&lt;/code&gt;, &lt;code&gt;lspkind.nvim&lt;/code&gt; (for UI icons), and &lt;code&gt;noice.nvim&lt;/code&gt; (for quiet UI feedback). However, it lacks certain advanced integrations, such as a dedicated plugin for displaying status (e.g., &lt;code&gt;lualine&lt;/code&gt; or &lt;code&gt;heirline&lt;/code&gt;) and tighter control interfaces.&lt;/p&gt;

&lt;p&gt;As of now, Windsurf has no official plugins for &lt;code&gt;telescope.nvim&lt;/code&gt;, nor does it expose much internal state for customization or automation. The plugin focuses on simplicity and automatic configuration, which is suitable for most users but might limit advanced workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Adoption
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot is the current market leader in adoption, with over 1.8 million paid users as of late 2023. Its official plugin has more than 9,000 stars on GitHub, and its deep GitHub integration makes it an obvious choice for teams already invested in the Microsoft ecosystem.&lt;/p&gt;

&lt;p&gt;Windsurf, on the other hand, is quickly gaining ground. Formerly known as Codeium, it surpassed 700,000 users in 2024 and is used by over a thousand companies—many of which take advantage of its on-premises deployment option. The &lt;code&gt;windsurf.nvim&lt;/code&gt; plugin is still maturing, but it has already demonstrated solid technical stability and growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note on the VSCode vs NeoVim Experience
&lt;/h2&gt;

&lt;p&gt;It’s crucial to understand that both Copilot and Windsurf were originally designed with graphical editors in mind—primarily Visual Studio Code. This means that many of their native features, such as chat windows, PR integrations, and visual context navigation, were built assuming a rich UI.&lt;/p&gt;

&lt;p&gt;GitHub Copilot, for instance, shines brightest in VSCode with features like Copilot Chat, multi-file awareness, and integration with GitHub repositories. Within NeoVim, however, the experience is more limited, relying on third-party plugins to provide similar capabilities.&lt;/p&gt;

&lt;p&gt;Windsurf faces a similar scenario. While it does offer a dedicated NeoVim plugin—unlike Copilot, whose official Vim support is fairly limited—many advanced features remain exclusive to the VSCode extension. Still, its CLI-based client for terminal use is fast, reliable, and competitive.&lt;/p&gt;

&lt;p&gt;This mismatch between environments creates a noticeable gap. Features that feel revolutionary in VSCode are often not yet fully available or stable in the NeoVim ecosystem, directly impacting the experience of users who prefer a keyboard-centric workflow.&lt;/p&gt;

&lt;p&gt;That said, this note is not intended to suggest a change of editor. Rather, it highlights the need for broader vendor support and awareness regarding the growing demand from developers who choose terminal-based tools like NeoVim or Vim. Features that feel revolutionary in VSCode are often not yet fully available or stable in the NeoVim ecosystem, directly impacting the experience of users who prefer a keyboard-centric workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoring Methodology and Final Verdict
&lt;/h2&gt;

&lt;p&gt;Below, I present a comparative scoring of GitHub Copilot and Windsurf based on technical criteria, usage experience in NeoVim, and my own perception of their strengths and limitations. This evaluation is subjective but informed by real-world usage and priorities such as customization, stability, integration, and user control.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Copilot&lt;/th&gt;
&lt;th&gt;Windsurf&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup and Installation&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suggestion Quality&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context Awareness&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugin Ecosystem&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical Stability&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customizability&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy Handling&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model Intelligence&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NeoVim Support&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Popularity and Adoption&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total Score:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copilot:&lt;/strong&gt; 76 points&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windsurf:&lt;/strong&gt; 90 points&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References and Resources
&lt;/h2&gt;

&lt;p&gt;To support further exploration and experimentation, I’ve compiled the following resources. These links include official documentation, plugin repositories, and project homepages, offering deeper insights into setup, customization, and ongoing development of both Copilot and Windsurf:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot Official Site&lt;/a&gt; — Overview of Copilot’s capabilities, pricing, and integrations from GitHub.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/github/copilot.vim" rel="noopener noreferrer"&gt;Copilot.nim (Official Vim Plugin)&lt;/a&gt; — The official plugin maintained by GitHub for Vim and NeoVim.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/zbirenbaum/copilot.lua" rel="noopener noreferrer"&gt;Copilot.lua (Community Plugin)&lt;/a&gt; — A modern, extensible alternative to the official Copilot plugin.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/zbirenbaum/copilot-cmp" rel="noopener noreferrer"&gt;Copilot-cmp&lt;/a&gt; — Enables Copilot suggestions to integrate with &lt;code&gt;nvim-cmp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AndreM222/copilot-lualine" rel="noopener noreferrer"&gt;Copilot-lualine&lt;/a&gt; — A lightweight plugin to show Copilot’s status in &lt;code&gt;lualine&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Exafunction/windsurf.nvim" rel="noopener noreferrer"&gt;Windsurf (Codeium) NeoVim Plugin&lt;/a&gt; — The official plugin for using Windsurf inside NeoVim.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.codeium.com/" rel="noopener noreferrer"&gt;Windsurf Website&lt;/a&gt; — General access to Windsurf’s features, documentation, and signup.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/neovim/comments/18klz7x/codeium_vs_copilot_performance_analysis/" rel="noopener noreferrer"&gt;Codeium vs Copilot Performance Thread (Reddit)&lt;/a&gt; — Community-driven insights and real-world performance observations.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2303.17564" rel="noopener noreferrer"&gt;AI Code Completion Benchmarks (2023)&lt;/a&gt; — Research paper comparing latency and accuracy across several AI coding tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I intend to keep this scorecard updated over time, as both tools are living projects in constant evolution. Changes in performance, integration capabilities, and community contributions may significantly shift the balance in future versions.&lt;/p&gt;

&lt;p&gt;Both Copilot and Windsurf bring considerable value to NeoVim users. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windsurf&lt;/strong&gt; stands out for its customizability, contextual precision, privacy controls, and free usage model, making it a compelling option for developers who want full control over their environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copilot&lt;/strong&gt;, meanwhile, remains a highly accessible choice for those already embedded in the GitHub ecosystem. Its performance, ease of use, and extensive community support make it a solid pick—especially if you're using VSCode as your primary editor.&lt;/p&gt;

&lt;p&gt;Ultimately, the best choice depends on how you work, what you prioritize, and where you want your toolchain to take you.&lt;/p&gt;

&lt;p&gt;If you use either of these tools in NeoVim, or have insights, configurations, or edge cases you'd like to share, I’d love to hear from you. Your input could help improve this comparison and guide future updates. And if you'd like to see a follow-up article with detailed configuration instructions and related plugin setups, just let me know! Your input could help improve this comparison and guide future updates.&lt;/p&gt;

&lt;p&gt;Thank you for reading! I hope this article offered clarity and practical value for your workflow. As both tools are living projects in constant evolution. Changes in performance, integration capabilities, and community contributions may significantly shift the balance in future versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article reflects my personal and technical analysis based on actual usage of both tools in NeoVim. The preferences, perceptions, and scores expressed are mine alone and are not intended to define universal standards. Every developer should evaluate these tools based on their own context and needs.&lt;/p&gt;

</description>
      <category>neovim</category>
      <category>ai</category>
      <category>githubcopilot</category>
      <category>codeium</category>
    </item>
    <item>
      <title>Why You Should Migrate to NeoVim</title>
      <dc:creator>Jonatas Sas</dc:creator>
      <pubDate>Fri, 25 Apr 2025 22:50:49 +0000</pubDate>
      <link>https://dev.to/jonatas-sas/why-you-should-migrate-to-neovim-1bl</link>
      <guid>https://dev.to/jonatas-sas/why-you-should-migrate-to-neovim-1bl</guid>
      <description>&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%2Fnsqy1efh0nuggd9os80v.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%2Fnsqy1efh0nuggd9os80v.png" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I've been programming since 2004, and my journey began right inside the banking sector. Back then, my days were filled with Perl scripts — using Interwoven Templates — and plenty of JavaScript to bring life to web frontends. It was a different world: heavy systems, strict environments, tools that demanded real discipline.&lt;/p&gt;

&lt;p&gt;During that time, I worked with VI and other classic tools that forced you to know exactly what you were doing. There were no "autocompletes" or "friendly interfaces" to save you. It was raw, and in some ways, it built the foundation I stand on today.&lt;/p&gt;

&lt;p&gt;As time passed, PHP entered my life and became a strong focus. I dabbled with other languages when needed, but PHP remained central. I explored IDEs, one after another — Eclipse, NetBeans — until I found my home for a long time: PhpStorm. Without exaggeration, PhpStorm boosted my work, sharpened my delivery, and opened a new chapter for me as a developer.&lt;/p&gt;

&lt;p&gt;If you're still on VSCode today, let me offer some honest advice: consider trying NeoVim or PhpStorm. Both can change the way you feel about building software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Turning Point: Speed and Workflow
&lt;/h2&gt;

&lt;p&gt;Managing several projects simultaneously started exposing cracks in my workflow. Even the mighty PhpStorm, with all its power, couldn't fully hide the latency creeping in when things got too heavy.&lt;/p&gt;

&lt;p&gt;At different moments, I tried moving to Vim and later NeoVim. I failed a few times. And if you try, you might fail too — at least at first. That's okay.&lt;/p&gt;

&lt;p&gt;You need at least a month — a real, honest month — to migrate properly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your speed will drop.&lt;/li&gt;
&lt;li&gt;You will doubt yourself.&lt;/li&gt;
&lt;li&gt;You'll want to give up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But migration isn't some mystical leap. It's a strategy. It's an act of patience and adaptation.&lt;/p&gt;

&lt;p&gt;Some practical advice to ease the path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start by using Vim keybindings inside your IDE (e.g., IdeaVim in JetBrains).&lt;/li&gt;
&lt;li&gt;Get comfortable progressively, not all at once.&lt;/li&gt;
&lt;li&gt;Explore NeoVim's configuration files and slowly make them your own.&lt;/li&gt;
&lt;li&gt;Embrace Lua — the quiet power behind NeoVim's modern capabilities (and a proud Brazilian export from PUC-RJ!).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Choose NeoVim?
&lt;/h2&gt;

&lt;p&gt;Because it demands something precious: understanding.&lt;/p&gt;

&lt;p&gt;You have to learn how your environment is structured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How each tool plugs into the bigger picture.&lt;/li&gt;
&lt;li&gt;How workflows aren't accidents — they're systems you consciously create.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you step away from relying on the mouse and move into a world of pure keyboard-driven navigation, something strange happens: you start thinking differently. Your code becomes an extension of your hands, and your focus deepens. It’s not faster just for the sake of speed. It’s faster because it’s closer to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maximizing Focus and Brain Efficiency
&lt;/h2&gt;

&lt;p&gt;Context-switching kills focus. Every time you switch apps — jumping from an IDE to Postman, to FileZilla, to the terminal — your brain spends energy adapting to new visual contexts.&lt;/p&gt;

&lt;p&gt;In a terminal-driven environment like NeoVim, everything stays cohesive. You run your Git commands. You write your code. You test APIs. You manage servers. All within the same ecosystem.&lt;/p&gt;

&lt;p&gt;That continuity matters. It’s not just saving milliseconds. It’s preserving your flow state, protecting that rare moment when you’re fully immersed.&lt;/p&gt;

&lt;p&gt;Programming, at its best, feels like water flowing through your mind. NeoVim helps preserve that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Cost of Traditional IDEs
&lt;/h2&gt;

&lt;p&gt;Traditional IDEs, for all their polish, slowly start shaping you in their image. You stop thinking about how you want to work. You just accept how they want you to work.&lt;/p&gt;

&lt;p&gt;Abstraction is helpful at first. But for a developer who wants to master the craft, too much abstraction becomes a cage.&lt;/p&gt;

&lt;p&gt;NeoVim breaks that. It gives you back control. It reminds you that your environment should serve you — not the other way around.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Reflection
&lt;/h2&gt;

&lt;p&gt;NeoVim isn’t about being cool. It isn’t about showing off speed.&lt;/p&gt;

&lt;p&gt;It’s about ownership.&lt;/p&gt;

&lt;p&gt;It’s about building an environment that molds itself to you. One where your hands, your thoughts, your habits — all flow together into something that feels honest and natural.&lt;/p&gt;

&lt;p&gt;Once you taste that freedom, it's very hard to accept anything less.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Start Your NeoVim Journey
&lt;/h2&gt;

&lt;p&gt;Start simple. Start humbly.&lt;/p&gt;

&lt;p&gt;Use something like &lt;a href="https://github.com/nvim-lua/kickstart.nvim" rel="noopener noreferrer"&gt;kickstart.nvim&lt;/a&gt; — a minimalist, thoughtful configuration that gives you a strong foundation without overwhelming you.&lt;/p&gt;

&lt;p&gt;Don't rush to install 200 plugins. Don't chase someone's shiny dotfiles.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn each configuration block.&lt;/li&gt;
&lt;li&gt;Understand why each tool is there.&lt;/li&gt;
&lt;li&gt;Build your NeoVim the way you'd build your own house: one brick at a time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for deeper dives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://neovim.io/doc/" rel="noopener noreferrer"&gt;Official NeoVim Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/neovim/neovim" rel="noopener noreferrer"&gt;Neovim GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rockerBOO/awesome-neovim" rel="noopener noreferrer"&gt;Awesome Neovim (Community Curated Plugins)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more you walk the path, the more natural it becomes. Trust the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming Soon
&lt;/h2&gt;

&lt;p&gt;I'm putting together a new article that will explore how to set up an efficient PHP development environment inside NeoVim. It'll cover everything from getting the PHP Language Server running to smart autocompletion, running tests, and even debugging right from your terminal — all without ever needing to leave the comfort of your editor.&lt;/p&gt;

&lt;p&gt;If you're working with PHP and have ever dreamed of a more streamlined, enjoyable setup, keep an eye out. This one's for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Channels
&lt;/h2&gt;

&lt;p&gt;Looking to keep learning? Here are a few creators who know what they're doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/c/TJDeVries" rel="noopener noreferrer"&gt;TJ DeVries&lt;/a&gt; — NeoVim core developer, excellent technical depth.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/c/ThePrimeagen" rel="noopener noreferrer"&gt;ThePrimeagen&lt;/a&gt; — Practical advice, high-energy content, and real talk about real workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many others too. Find the ones who make you want to open your terminal and start coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appreciation
&lt;/h2&gt;

&lt;p&gt;I want to extend a heartfelt thank you to everyone who contributes to the Vim and NeoVim ecosystems — from developers to documenters, testers to maintainers, advocates to quiet supporters. You are the proof that open source is more than just code; it is vision, persistence, and community. Without your dedication and passion, tools like these would not be possible, and the journey of many developers, including mine, would have been very different.&lt;/p&gt;

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

&lt;p&gt;We don't code for likes. We don't tweak our editors to impress anyone.&lt;/p&gt;

&lt;p&gt;We build because it makes us better. Because it sharpens our craft.&lt;/p&gt;

&lt;p&gt;Let's keep building — with focus, with respect, and with the freedom to be exactly who we are as developers.&lt;/p&gt;

</description>
      <category>neovim</category>
      <category>developers</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Simplify Many-to-Many Relationships in Yii2 with yii2-m2m-behavior</title>
      <dc:creator>Jonatas Sas</dc:creator>
      <pubDate>Tue, 22 Apr 2025 14:22:05 +0000</pubDate>
      <link>https://dev.to/jonatas-sas/simplify-many-to-many-relationships-in-yii2-with-yii2-m2m-behavior-59lk</link>
      <guid>https://dev.to/jonatas-sas/simplify-many-to-many-relationships-in-yii2-with-yii2-m2m-behavior-59lk</guid>
      <description>&lt;p&gt;Managing many-to-many relationships in Yii2 just got a lot easier.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;yii2-m2m-behavior&lt;/code&gt; package allows you to assign related models directly using virtual attributes like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tagIds&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="mi"&gt;2&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;p&gt;Under the hood, the behavior handles all the syncing through the junction table — no need to manually call &lt;code&gt;link()&lt;/code&gt; or &lt;code&gt;unlink()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means less boilerplate, fewer mistakes, and cleaner code when dealing with junction tables.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 What does it solve?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automatically links/unlinks models in many-to-many relations&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;virtual attributes&lt;/strong&gt; (e.g., &lt;code&gt;tagIds&lt;/code&gt;, &lt;code&gt;categoryIds&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Allows saving &lt;strong&gt;extra columns&lt;/strong&gt; in the junction table (e.g., timestamps, flags)&lt;/li&gt;
&lt;li&gt;Keeps everything in sync on insert, update, and delete&lt;/li&gt;
&lt;li&gt;Uses native Yii2 APIs (&lt;code&gt;link()&lt;/code&gt;, &lt;code&gt;unlink()&lt;/code&gt;, &lt;code&gt;populateRelation()&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ActiveRecord&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;behaviors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'tags'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'class'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;LinkManyToManyBehavior&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'relation'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tags'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'referenceAttribute'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tagIds'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'tag_id'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;viaTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'item_tag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'item_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'id'&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;Then, just do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tagIds&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="mi"&gt;2&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="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the junction table will be updated automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Controller + View Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Controller&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;actionCreate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Yii&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'view'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'create'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'model'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'availableTags'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;ArrayHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- View (create.php) --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt; &lt;span class="nv"&gt;$form&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tagIds'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;checkboxList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$availableTags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Quality &amp;amp; Coverage
&lt;/h2&gt;

&lt;p&gt;This package was built with &lt;strong&gt;robustness&lt;/strong&gt; in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100% code coverage with PHPUnit&lt;/li&gt;
&lt;li&gt;CI-enforced coverage gate&lt;/li&gt;
&lt;li&gt;Every edge case tested, including misconfigured relations and corrupted states&lt;/li&gt;
&lt;li&gt;Focused on DX: helpful exception messages and fail-fast behavior&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 What’s in version 2.1.0
&lt;/h2&gt;

&lt;p&gt;Version 2.1.0 brings deeper introspection and new tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic synchronization even when relations are populated with &lt;code&gt;with()&lt;/code&gt; or &lt;code&gt;populateRelation()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isReferenceRelationDirty()&lt;/code&gt; method to detect mismatch between relation and reference attribute&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;computeRelationHash()&lt;/code&gt; for internal tracking of changes&lt;/li&gt;
&lt;li&gt;Better internal consistency and refactors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP &lt;strong&gt;8.1&lt;/strong&gt; to &lt;strong&gt;8.4&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Yii2 &lt;strong&gt;~2.0.0&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧭 What’s next?
&lt;/h2&gt;

&lt;p&gt;We’re working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validators for virtual attributes (e.g. &lt;code&gt;tagIds&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Better internal caching and lazy loading&lt;/li&gt;
&lt;li&gt;Custom events for hooks before/after sync&lt;/li&gt;
&lt;li&gt;Debug tools for inspecting link/unlink actions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Try it now
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require jonatas-sas/yii2-m2m-behavior
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📚 &lt;a href="https://github.com/jonatas-sas/yii2-m2m-behavior" rel="noopener noreferrer"&gt;Full documentation and examples on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback and contributions are very welcome!&lt;/p&gt;

</description>
      <category>php</category>
      <category>yii2</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
