<?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: Duskel</title>
    <description>The latest articles on DEV Community by Duskel (@duskel).</description>
    <link>https://dev.to/duskel</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%2F4017462%2F20a13c9f-dc62-4851-baab-28c34cc8dbd3.png</url>
      <title>DEV Community: Duskel</title>
      <link>https://dev.to/duskel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/duskel"/>
    <language>en</language>
    <item>
      <title>WordPress to Next.js Migration: A 12-Month Cost Test Before You Rebuild</title>
      <dc:creator>Duskel</dc:creator>
      <pubDate>Mon, 27 Jul 2026 08:54:10 +0000</pubDate>
      <link>https://dev.to/duskel/wordpress-to-nextjs-migration-a-12-month-cost-test-before-you-rebuild-1koe</link>
      <guid>https://dev.to/duskel/wordpress-to-nextjs-migration-a-12-month-cost-test-before-you-rebuild-1koe</guid>
      <description>&lt;h2&gt;
  
  
  WordPress 7.1 entered beta on July 15. Your plugin bill stays.
&lt;/h2&gt;

&lt;p&gt;The final release is due August 19, 2026. A core update can fix WordPress bugs, but it cannot remove the upkeep created by a page builder, shop system, security add-on, cache and forgotten plugins pulling in different directions.&lt;/p&gt;

&lt;p&gt;A WordPress to Next.js migration makes sense when that upkeep costs more than rebuilding the visitor-facing site. Run the numbers before choosing a stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 12-month cost test
&lt;/h2&gt;

&lt;p&gt;Write down two totals using your own invoices and time logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep the current site
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hosting and paid plugin renewals&lt;/li&gt;
&lt;li&gt;Staff or agency hours spent on updates and conflicts&lt;/li&gt;
&lt;li&gt;Sales lost during slow pages or outages&lt;/li&gt;
&lt;li&gt;Work delayed because the current setup blocks a change&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rebuild the visitor-facing site
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Design and development&lt;/li&gt;
&lt;li&gt;Moving content and checking every page&lt;/li&gt;
&lt;li&gt;Redirecting old URLs&lt;/li&gt;
&lt;li&gt;Hosting and upkeep for the first year&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compare the totals over the same 12 months. A rebuild has a business case when its cost is lower and it removes a repeated source of lost sales or staff time.&lt;/p&gt;

&lt;h2&gt;
  
  
  A lower-risk migration shape
&lt;/h2&gt;

&lt;p&gt;WordPress can remain the writing screen your team knows. Next.js becomes the website customers see.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;List the content types editors use today.&lt;/li&gt;
&lt;li&gt;Pull published content from WordPress into the new pages.&lt;/li&gt;
&lt;li&gt;Build common pages ahead of each visit so they open quickly.&lt;/li&gt;
&lt;li&gt;Refresh a page after an editor publishes a change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This keeps the familiar editor while removing many plugins from the customer-facing site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protect search traffic before launch
&lt;/h2&gt;

&lt;p&gt;Every existing URL needs a destination on the new site. Build a redirect list before any page moves.&lt;/p&gt;

&lt;p&gt;Also check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page titles and descriptions&lt;/li&gt;
&lt;li&gt;The sitemap sent to search engines&lt;/li&gt;
&lt;li&gt;The setting that tells Google which page is the official version&lt;/li&gt;
&lt;li&gt;Links inside older articles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run a crawl of the old site and the new one. Any missing page should block launch until it has a redirect or an intentional replacement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cases where staying on WordPress wins
&lt;/h2&gt;

&lt;p&gt;Keep the current setup when the site is fast enough, the team depends on plugin-heavy shop features, or editors need changes that would require custom work in Next.js.&lt;/p&gt;

&lt;p&gt;A rebuild should solve a measured cost. Version excitement alone is a poor reason to fund one.&lt;/p&gt;

&lt;p&gt;Scope a WordPress rebuild: duskel.com/services/wordpress-development&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>seo</category>
    </item>
    <item>
      <title>RAG Chatbot Development for Small Business: What Actually Changed When We Swapped in Claude Sonnet 5</title>
      <dc:creator>Duskel</dc:creator>
      <pubDate>Mon, 06 Jul 2026 16:40:00 +0000</pubDate>
      <link>https://dev.to/duskel/rag-chatbot-development-for-small-business-what-actually-changed-when-we-swapped-in-claude-sonnet-5-34mj</link>
      <guid>https://dev.to/duskel/rag-chatbot-development-for-small-business-what-actually-changed-when-we-swapped-in-claude-sonnet-5-34mj</guid>
      <description>&lt;p&gt;Claude Sonnet 5 became the default free and Pro model on July 1. We had it running inside a client's retrieval pipeline four days later — not a toy demo, a production RAG chatbot for a small business client with about 40,000 support documents and a strict "don't make things up" requirement.&lt;/p&gt;

&lt;p&gt;Here's what actually changed, and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The client came to us the way a lot of small businesses do when they want to hire a developer to build a RAG system on their own data: a pile of PDFs, a shared drive, and a support inbox getting the same 30 questions on repeat. No enterprise budget, no in-house ML team, just a real need to stop answering the same email every day.&lt;/p&gt;

&lt;p&gt;Our stack for this one is boring on purpose: pgvector for retrieval, a thin re-ranking step, and whatever LLM sits at the end answering with citations. That last part is a config value, not a rewrite. Swapping providers or model versions should be a one-line change. If it isn't, your architecture is the actual problem, not the model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generationModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anthropic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// was claude-sonnet-4-6&lt;/span&gt;
  &lt;span class="na"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&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;h2&gt;
  
  
  What got better
&lt;/h2&gt;

&lt;p&gt;Two things stood out in the first 48 hours of testing against our existing eval set (about 120 real support questions with known-good answers):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer confident wrong answers.&lt;/strong&gt; Sonnet 5 was noticeably more willing to say "the documents don't cover this" instead of blending two unrelated policy sections into something plausible-sounding. That's the failure mode that actually costs small businesses money — not the chatbot being unhelpful, but the chatbot being wrong with a straight face.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better use of retrieved context under pressure.&lt;/strong&gt; When we deliberately fed it 8-10 chunks instead of 3-4 (a common real-world scenario when queries are vague), the answer quality held up better than the previous model. Less "picks the first chunk and ignores the rest."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Latency was roughly flat. Cost per query was flat. Neither was the reason to move.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't change
&lt;/h2&gt;

&lt;p&gt;The model swap did not fix bad chunking, and it did not fix a retrieval step that was already returning the wrong documents. We still spent most of our week on the boring stuff: chunk size, metadata filters, and re-ranking thresholds. That's the part of RAG chatbot development for small business clients that never makes it into vendor pitch decks, because it's not a feature you can screenshot.&lt;/p&gt;

&lt;p&gt;There's a real backlash brewing right now about AI-written code quality — a widely cited 153-million-line analysis this week shows duplication up roughly 4x and rising churn where teams lean hard on agents without review. We see the same pattern in RAG systems: teams swap in a shinier model and expect it to paper over a retrieval layer nobody actually designed. It won't. The model is maybe 20% of why a RAG chatbot hallucinates. The other 80% is what you feed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual takeaway
&lt;/h2&gt;

&lt;p&gt;If your RAG pipeline is architected so the generation model is a config value, model releases are good news you can act on in days, not a migration project. If it's not — if "switch models" means touching prompt templates in six different files — that's worth fixing before you worry about which model is smartest this quarter.&lt;/p&gt;

&lt;p&gt;We're a founder-led software studio, not a faceless agency, and we test new model releases against real client pipelines because that's the only way to know if they matter. If you're trying to hire a developer to build a RAG system on your own data — a small business, not an enterprise budget — see how we scope it at &lt;a href="https://duskel.com/services" rel="noopener noreferrer"&gt;duskel.com/services&lt;/a&gt; or write to &lt;a href="mailto:hello@duskel.com"&gt;hello@duskel.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>RAG Chatbot Development for B2B: Why We Stopped Hard-Coding One LLM Vendor</title>
      <dc:creator>Duskel</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:39:26 +0000</pubDate>
      <link>https://dev.to/duskel/rag-chatbot-development-for-b2b-why-we-stopped-hard-coding-one-llm-vendor-4f8j</link>
      <guid>https://dev.to/duskel/rag-chatbot-development-for-b2b-why-we-stopped-hard-coding-one-llm-vendor-4f8j</guid>
      <description>&lt;h2&gt;
  
  
  The pipeline that broke on a Tuesday
&lt;/h2&gt;

&lt;p&gt;In June 2026, Anthropic's Claude was pulled from availability for 20 days in several regions under export-control rules. If you'd built a client's RAG chatbot with a single hard-coded call to &lt;code&gt;anthropic.messages.create()&lt;/code&gt;, that client's support bot went dark. Not because the model got worse. Because the vendor got yanked.&lt;/p&gt;

&lt;p&gt;We run a small studio building RAG systems for B2B clients, several of them outside the US, and that's the exact scenario we now design against. Not as a hypothetical — as something that already happened to teams who didn't plan for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most RAG chatbot builds get the wrong thing right
&lt;/h2&gt;

&lt;p&gt;When an agency pitches a "RAG chatbot development" project, the demo is always the same: embed some docs, wire up a vector store, call one model, done. It answers questions well in the sales call. Nobody stress-tests what happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the vendor changes pricing overnight&lt;/li&gt;
&lt;li&gt;the vendor's API gets export-restricted in the client's country&lt;/li&gt;
&lt;li&gt;the vendor deprecates the model you built prompts around&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We treat the LLM call as the &lt;em&gt;least&lt;/em&gt; stable part of the stack, and design everything else so swapping it out is a config change, not a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we actually build
&lt;/h2&gt;

&lt;p&gt;A thin provider interface sits between the retrieval layer and the model call. Retrieval, chunking, reranking, and citation logic never touch a vendor SDK directly.&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;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&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="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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="o"&gt;-&amp;gt;&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;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClaudeProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;anthropic_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LongCatProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;longcat_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="c1"&gt;# swap providers via config, not a redeploy
&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROVIDER_REGISTRY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LLM_PROVIDER&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not clever. That's the point — boring abstractions are the ones that survive a vendor outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open-weight models changed the calculus
&lt;/h2&gt;

&lt;p&gt;LongCat-2.0 shipped this month under a full MIT license — no regional restrictions, free to fine-tune and redistribute. For a foreign client who just watched a US-origin model vanish for three weeks, that's not a curiosity, it's a fallback path. We're not saying drop Claude — Sonnet 5, out since June 30, is genuinely the sharpest agentic model we've used in production, and it's still our default for reasoning-heavy retrieval. We're saying don't let one vendor be a single point of failure for a client's support desk or internal knowledge base.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trust gap nobody's pricing in
&lt;/h2&gt;

&lt;p&gt;There's a stat going around this week: 84% of developers now use AI coding tools, but only 29% trust the output unsupervised. We see the same split with RAG specifically — clients love what a demo can do, then ask "what happens when it's wrong in front of a customer?" The honest answer is: it will be, occasionally, and your architecture needs a human review step and a citation trail, not just a bigger prompt.&lt;/p&gt;

&lt;p&gt;That's the part of AI RAG system integration for small business that gets skipped when the pitch is all demo and no failure mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you're scoping one
&lt;/h2&gt;

&lt;p&gt;If you're evaluating a RAG chatbot development agency for B2B work, ask two questions before you ask about accuracy: what happens when the model vendor changes terms, and can you point the same pipeline at a different model without touching retrieval code. If the answer is "we'd rebuild it," you're buying a demo, not a system.&lt;/p&gt;

&lt;p&gt;We've been building this vendor-flexible pattern into every RAG engagement lately, partly because it's good architecture, partly because the last month proved it isn't optional for clients operating outside the US.&lt;/p&gt;

&lt;p&gt;If you're scoping something like this, &lt;a href="https://duskel.com/services" rel="noopener noreferrer"&gt;duskel.com/services&lt;/a&gt; has how we approach it, or just email &lt;a href="mailto:hello@duskel.com"&gt;hello@duskel.com&lt;/a&gt; and tell us what you're building.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>webdev</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
