<?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: Njabulo Majozi</title>
    <description>The latest articles on DEV Community by Njabulo Majozi (@njabulomajozi).</description>
    <link>https://dev.to/njabulomajozi</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%2F199432%2F9eaded19-33ba-435e-8c65-00b31acffd77.png</url>
      <title>DEV Community: Njabulo Majozi</title>
      <link>https://dev.to/njabulomajozi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/njabulomajozi"/>
    <language>en</language>
    <item>
      <title>Building Prude</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Wed, 17 Sep 2025 08:30:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/prude-transform-your-communication-eo9</link>
      <guid>https://dev.to/njabulomajozi/prude-transform-your-communication-eo9</guid>
      <description>&lt;p&gt;Hey everyone! 👋&lt;/p&gt;

&lt;p&gt;I've been working on something pretty cool that I'm excited to share with you all. It's called Prude - essentially, it's an AI-powered app that helps address one of the biggest problems we all face: being overwhelmed by emails, messages, and decisions.&lt;/p&gt;

&lt;p&gt;You know that feeling when you open your inbox and there are 50+ emails, and you don't even know where to start? Or when you're getting pinged on Slack, WhatsApp, and Gmail all at once and you're drowning in notifications? That's exactly what this app tackles.&lt;/p&gt;

&lt;p&gt;Here's what it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart Organisation: It automatically reads through all your messages and determines what requires a reply, a calendar event, or a task.&lt;/li&gt;
&lt;li&gt;AI Insights: Instead of just showing you messages, it gives you a daily "digest" that summarises what needs your attention and suggests actions&lt;/li&gt;
&lt;li&gt;Decision Support: For bigger decisions, it connects the dots between your
conversations, projects, and people to give you a better context&lt;/li&gt;
&lt;li&gt;One Dashboard: Instead of jumping between Gmail, Slack, Teams, etc., you see everything that matters in one place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like having a really smart assistant who reads all your messages and then gives you a brief: "Here are the 3 things that actually need your attention today, here's why they matter, and here's what you should probably do about them."&lt;/p&gt;

&lt;p&gt;It's designed for professionals and busy people who are tired of feeling like they're always behind on their communications. I'm really proud of how it's turning out!&lt;/p&gt;

&lt;p&gt;Still in the building phase, sign up for updates at  &lt;a href="https://prude.onglx.ai/" rel="noopener noreferrer"&gt;https://prude.onglx.ai/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear your thoughts!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gmail</category>
      <category>aws</category>
      <category>ios</category>
    </item>
    <item>
      <title>Building OpenAI API Compatibility with AWS Bedrock</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Tue, 16 Sep 2025 08:30:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/building-openai-api-compatibility-with-aws-bedrock-pj0</link>
      <guid>https://dev.to/njabulomajozi/building-openai-api-compatibility-with-aws-bedrock-pj0</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Many developers already rely on the OpenAI Chat Completions API. But what if your platform needs &lt;strong&gt;vendor independence&lt;/strong&gt; and &lt;strong&gt;cost optimisation&lt;/strong&gt; by running inference on AWS Bedrock (or GCP Vertex AI) — while still giving developers a &lt;strong&gt;drop-in OpenAI-compatible API&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That was the challenge I faced when building &lt;a href="https://deploy.onglx.io/?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=promotion" rel="noopener noreferrer"&gt;OnglX deploy&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Context &amp;amp; Architectural Decisions
&lt;/h2&gt;

&lt;p&gt;I wanted developers to adopt OnglX deploy with &lt;strong&gt;zero code changes&lt;/strong&gt;. That meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support the &lt;strong&gt;OpenAI API format&lt;/strong&gt; as-is.&lt;/li&gt;
&lt;li&gt;Run inference on Bedrock, not OpenAI.&lt;/li&gt;
&lt;li&gt;Keep things extensible for multi-cloud (AWS + GCP).&lt;/li&gt;
&lt;li&gt;Secure it with &lt;strong&gt;API keys&lt;/strong&gt; and serverless IAM best practices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architectural bet: a &lt;strong&gt;protocol translation layer&lt;/strong&gt; that accepts OpenAI-style requests and translates them to provider-specific formats — then back again.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Specific Challenge
&lt;/h2&gt;

&lt;p&gt;Bedrock (and other providers) models don’t speak the same “language.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude&lt;/strong&gt; requires separate handling of system prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Llama&lt;/strong&gt; expects a continuation-style prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Titan&lt;/strong&gt; only supports &lt;code&gt;inputText&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even token usage reporting and error messages differ.&lt;/p&gt;

&lt;p&gt;So: how do you unify all that while still looking and behaving like OpenAI?&lt;/p&gt;




&lt;h2&gt;
  
  
  Solution Approaches I Considered
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provider-Specific Endpoints&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;✅ Cleaner per model family&lt;/li&gt;
&lt;li&gt;❌ Breaks drop-in compatibility&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified Translation Layer (Chosen)&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;✅ Works with OpenAI clients directly&lt;/li&gt;
&lt;li&gt;✅ Extensible for multi-cloud&lt;/li&gt;
&lt;li&gt;❌ More translation logic &amp;amp; testing required&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Trade-Offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compatibility vs Performance&lt;/strong&gt; → We favoured compatibility. Cold starts and translation overhead are acceptable since inference latency dominates anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-cloud support vs Simplicity&lt;/strong&gt; → Added complexity, but ensures portability and avoids lock-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless vs Dedicated Infra&lt;/strong&gt; → Serverless chosen for cost efficiency and scaling, at the expense of slightly higher cold start latency.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Implementation Details
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Request Translation Example
&lt;/h3&gt;

&lt;p&gt;System messages in OpenAI can appear anywhere, but Claude needs them to be separate:&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;system_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;conversation_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;payload&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;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;conversation_messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&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="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;system_messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Model-specific handling:&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;if&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;model_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Claude format
&lt;/span&gt;&lt;span class="k"&gt;elif&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;model_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta.llama&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Llama continuation format
&lt;/span&gt;&lt;span class="k"&gt;elif&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;model_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amazon.titan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Titan inputText format
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Response Translation Example
&lt;/h3&gt;

&lt;p&gt;Unifying token usage:&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;if&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;model_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;usage&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;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage&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;input_tokens&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;completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage&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;output_tokens&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;total_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage&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;input_tokens&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="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usage&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;output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Error mapping to OpenAI style:&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;except&lt;/span&gt; &lt;span class="n"&gt;ClientError&lt;/span&gt; &lt;span class="k"&gt;as&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;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error&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;Code&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;ValidationException&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid request or model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Infrastructure Setup
&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.amazonaws.com%2Fuploads%2Farticles%2Frjlez3a7dmuz124flmok.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%2Frjlez3a7dmuz124flmok.png" alt="AWS Infra" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Gateway v2&lt;/strong&gt; (CORS + auth)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB&lt;/strong&gt; (API key management with TTL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda&lt;/strong&gt; (Python 3.12, 512MB, 30s timeout)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Bedrock&lt;/strong&gt; (AI Models offering)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM&lt;/strong&gt; (least-privilege Bedrock + DynamoDB access)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terraform example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lambda_function"&lt;/span&gt; &lt;span class="s2"&gt;"api"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;runtime&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"python3.12"&lt;/span&gt;
  &lt;span class="nx"&gt;timeout&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
  &lt;span class="nx"&gt;memory_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Results &amp;amp; Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts&lt;/strong&gt; aren’t a big issue since inference latency dominates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;512MB Lambda&lt;/strong&gt; was the sweet spot — lower failures, higher waste costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model prefix detection&lt;/strong&gt; was a clean way to handle provider quirks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error translation&lt;/strong&gt; was critical for dev UX: users expect OpenAI-like errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, &lt;strong&gt;developers could point their OpenAI clients to our endpoint without code changes.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Apply This Approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You need &lt;strong&gt;drop-in OpenAI API compatibility&lt;/strong&gt; but want to use another provider (AWS/GCP/self-hosted).&lt;/li&gt;
&lt;li&gt;You’re building &lt;strong&gt;multi-cloud AI infra&lt;/strong&gt; and need consistent APIs.&lt;/li&gt;
&lt;li&gt;You prioritise &lt;strong&gt;developer adoption and compatibility&lt;/strong&gt; over raw performance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Call to Action
&lt;/h2&gt;

&lt;p&gt;If you’re building AI infra and want &lt;strong&gt;OpenAI compatibility without vendor lock-in&lt;/strong&gt;, this translation-layer pattern is worth considering.&lt;/p&gt;

&lt;p&gt;👉 Explore OnglX Deploy’s &lt;a href="https://deploy.onglx.io/docs/guide/inference/api?utm_source=devto&amp;amp;utm_medium=blog&amp;amp;utm_campaign=promotion" rel="noopener noreferrer"&gt;OpenAI-compatible API Docs&lt;/a&gt; and try deploying your own OpenAI-compatible API on AWS in minutes.&lt;/p&gt;

</description>
      <category>openai</category>
      <category>api</category>
      <category>aws</category>
      <category>claude</category>
    </item>
    <item>
      <title>001 - This is OnglX deploy</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Wed, 10 Sep 2025 08:30:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/001-this-is-onglx-deploy-13io</link>
      <guid>https://dev.to/njabulomajozi/001-this-is-onglx-deploy-13io</guid>
      <description>&lt;p&gt;Hey everyone! 👋&lt;/p&gt;

&lt;p&gt;Super excited to share something I’ve been working on: &lt;strong&gt;OnglX Deploy&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;It’s basically a tool that helps you take control of AI infrastructure without the crazy costs or headaches of managing it yourself.&lt;/p&gt;

&lt;p&gt;Here’s the problem: if you’ve ever tried running your own AI workloads, you know how painful it can be. Either you’re stuck paying high API costs to providers, or you’re lost in the weeds setting up cloud infra, Terraform, permissions, scaling, etc. It’s a nightmare.&lt;/p&gt;

&lt;p&gt;That’s exactly what OnglX Deploy fixes.&lt;/p&gt;

&lt;p&gt;Here’s what it does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your Cloud, Your Rules:&lt;/strong&gt; Deploy AI APIs directly to your own AWS (and soon GCP) accounts. No vendor lock-in, no data privacy worries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-Compatible:&lt;/strong&gt; You get the same API interface you already use, but running on your own infra.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Big Savings:&lt;/strong&gt; Cut costs by &lt;strong&gt;25–65%&lt;/strong&gt; by skipping middleman markups and paying your cloud provider directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer-Friendly:&lt;/strong&gt; One simple CLI command sets everything up—no endless configs, no hidden magic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extras Built-In:&lt;/strong&gt; It even ships with an &lt;strong&gt;Open WebUI&lt;/strong&gt; so you can interact with your models from day one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like &lt;strong&gt;Vercel for AI&lt;/strong&gt;, but instead of someone else’s servers, it’s &lt;em&gt;your&lt;/em&gt; cloud. One command and you’ve got a fully running inference API on AWS.&lt;/p&gt;

&lt;p&gt;I just shipped &lt;strong&gt;v0.1.43&lt;/strong&gt;, our first production-ready release 🎉.&lt;/p&gt;

&lt;p&gt;That means you can already:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spin up an API in AWS with &lt;code&gt;onglx-deploy init&lt;/code&gt; → &lt;code&gt;onglx-deploy deploy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run Bedrock models behind an OpenAI-compatible endpoint&lt;/li&gt;
&lt;li&gt;Manage everything with a lightweight Go-based CLI that installs via

&lt;ul&gt;
&lt;li&gt;Homebrew

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew tap onglx/homebrew-deploy-cli&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;brew install onglx-deploy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;npm

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;npm install -g @onglx/deploy-cli&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I wanted the developer experience to feel effortless, but under the hood, it’s built on a strong foundation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLI Layer:&lt;/strong&gt; A Go + Cobra-based CLI, a single static binary with zero dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration Layer:&lt;/strong&gt; OpenTofu runner coordinating deployments, rollbacks, and state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Layer:&lt;/strong&gt; Embedded OpenTofu modules for AWS (and soon GCP).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build System:&lt;/strong&gt; Monorepo powered by pnpm + Turborepo for speed and consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IaC:&lt;/strong&gt; Everything defined in OpenTofu, fully embedded inside the CLI — no external module wrangling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Distribution:&lt;/strong&gt; Binaries cross-compiled with GoReleaser and shipped across Homebrew and npm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that, so the experience for you is just one lightweight command.&lt;/p&gt;

&lt;p&gt;Getting to this release wasn’t easy. A few big hurdles I solved along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distribution from a Private Monorepo:&lt;/strong&gt; Package managers can’t pull from private repos, so I built public “release mirrors” (&lt;code&gt;onglx/homebrew-deploy-cli&lt;/code&gt;, &lt;code&gt;onglx/npm-deploy-cli&lt;/code&gt;) that automatically publishes binaries after every tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform-Specific Installs:&lt;/strong&gt; Needed a way for Homebrew/npm to auto-detect OS + architecture and fetch the right binary. Custom install scripts solved it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Release Automation:&lt;/strong&gt; Manual releases were painful, so I wired up GoReleaser + GitHub Actions to fully automate versioning, builds, and publishing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? A smooth, one-command install across macOS, Linux, and Windows.&lt;/p&gt;

&lt;p&gt;Still early days, but here’s the roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next:&lt;/strong&gt; OpenAI-compatible endpoint with GCP (Vertex AI + Cloud Functions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soon:&lt;/strong&gt; streaming responses, custom domains + SSL, and better secrets management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-term:&lt;/strong&gt; Multi-cloud, Azure support, and eventually expanding beyond inference into compute, storage, and databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever felt locked into someone else’s AI infra or sick of watching your API bill explode, this is for you.&lt;/p&gt;

&lt;p&gt;Would love your feedback—and if you want to try it, docs are live here 👉 &lt;a href="https://deploy.onglx.io/" rel="noopener noreferrer"&gt;https://deploy.onglx.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>infrastructureascode</category>
      <category>cli</category>
      <category>cloud</category>
    </item>
    <item>
      <title>KIRO - The AI IDE that works?</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Thu, 24 Jul 2025 07:00:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/kiro-the-ai-ide-that-works-1c5j</link>
      <guid>https://dev.to/njabulomajozi/kiro-the-ai-ide-that-works-1c5j</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;If you're a developer like me, you've probably experimented with AI coding tools like Cursor or Windsurf. And let's be honest, while they promise magic, they often deliver 'hallucinations' – losing context, butchering project structure, or completely misunderstanding your tech stack. It's frustrating, time-consuming, and frankly, defeats the purpose of 'assistance.'&lt;/p&gt;

&lt;p&gt;That's why when I stumbled upon Kiro, a new AI IDE from AWS, my ears perked up. It's a bold promise? To bring structure to AI coding through a concept called spec-driven development. This isn't just another tool; it might be the breakthrough we've been waiting for.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why It's On My Radar
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Problem Solved: Taming the AI Beast&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kiro directly confronts the AI Hallucination problem. Instead of refining prompts endlessly, Kiro uses your detailed specifications to ensure the AI stays perfectly aligned with your project's vision, architecture, and existing codebase. Think of it as giving the AI a blueprint, not just a vague idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Core Concept: Code with the Blueprint&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Forget prompting in the dark. Kiro's "Code with Spec" workflow is where the magic happens.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Requirements:&lt;/strong&gt; You define &lt;em&gt;what&lt;/em&gt; needs to be built.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design:&lt;/strong&gt; You detail &lt;em&gt;how&lt;/em&gt; – architecture, data models, error handling, even testing strategies. This is where you establish the guardrails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tasks:&lt;/strong&gt; Break down the work into actionable steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only &lt;em&gt;after&lt;/em&gt; you've approved these detailed specs does the AI generate code for each task, directly referencing your blueprint. This structured approach is a game-changer for consistency and accuracy.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Potential Impact: Beyond Just Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Reducing AI hallucinations isn't just about faster coding; it's about shifting our focus. Imagine less time debugging AI-generated messes and more time on high-level problem-solving and innovative design. Kiro's approach could lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher Code Quality:&lt;/strong&gt; AI adheres to established designs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Maintainability:&lt;/strong&gt; Code is generated with context and structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster Feature Delivery:&lt;/strong&gt; Less rework, more production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Industry Context: AWS's Secret Weapon?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kiro occupies a unique niche. While Cursor and Windsurf are strong contenders, Kiro's AWS parentage is a significant differentiator. We could see deep integrations with AWS cloud services, potentially making it the go-to IDE for developers heavily invested in the AWS ecosystem. The buzz is real: a waiting list for access confirms its high demand.&lt;/p&gt;

&lt;h1&gt;
  
  
  Personal Insight &amp;amp; Experience
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setup &amp;amp; First Impressions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As a VS Code fork, setup was a breeze – instantly familiar, and yes, you can export your existing extensions. My initial impressions were largely positive. The "agent hooks" and "agent steering" give a sense of control previously missing. The main adjustment? The &lt;em&gt;time&lt;/em&gt;. Going from ideation to final results isn't instant gratification; it requires that upfront spec work. But it's a worthwhile investment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pros &amp;amp; Cons&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unmatched Accuracy:&lt;/strong&gt; The spec-driven approach dramatically reduces hallucinations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed Workflow:&lt;/strong&gt; Guides you through requirements and design, improving overall project planning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code Familiarity:&lt;/strong&gt; Low UI learning curve for existing VS Code users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Backing:&lt;/strong&gt; Potential for powerful cloud integrations.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cons:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time Investment:&lt;/strong&gt; The initial spec phase takes more time than quick prompting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mindset Shift:&lt;/strong&gt; Requires developers to embrace a more structured AI-assisted workflow.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Cases &amp;amp; Applicability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I see Kiro shining brightest for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team Projects:&lt;/strong&gt; Ensuring consistent AI-generated code across a team, aligning with shared specs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Features:&lt;/strong&gt; Tackling intricate features where context and structure are paramount.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain Alignment:&lt;/strong&gt; Keeping the AI updated with current domain knowledge as features evolve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big learning curve isn't the UI, but getting developers to &lt;em&gt;think&lt;/em&gt; differently about AI-assisted development – less "write me code," more "build this &lt;em&gt;exactly&lt;/em&gt; according to my blueprint".&lt;/p&gt;

&lt;h1&gt;
  
  
  Broader Implications &amp;amp; Future Outlook
&lt;/h1&gt;

&lt;p&gt;Kiro isn't just a tool; it's a statement. It's bringing back core software development best practices (planning, design, documentation) to the forefront of AI-assisted coding. This aligns perfectly with trends towards more robust, reproducible, and maintainable codebases.&lt;/p&gt;

&lt;p&gt;I believe Kiro is poised to become a critical component in the development cycle, especially as AI continues to mature. It's the bridge between raw AI power and structured, enterprise-grade software development.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Kiro promises what many AI IDEs haven't delivered: reliable, context-aware code generation through a genius spec-driven approach. It's a trial that's showing immense promise for how we build software with AI. As Kiro puts it, it "helps you do your best work by bringing structure to AI coding with spec-driven development". I'm watching this space closely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you used Kiro? What are your thoughts or experiences? Feel free to connect with me&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kiro</category>
      <category>aws</category>
      <category>ai</category>
      <category>code</category>
    </item>
    <item>
      <title>Data Visibility: A Mongoose Middleware Case Study</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Tue, 15 Jul 2025 07:18:23 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/data-visibility-a-mongoose-middleware-case-study-35e9</link>
      <guid>https://dev.to/njabulomajozi/data-visibility-a-mongoose-middleware-case-study-35e9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Situation: Unapproved orders displayed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As part of a recent feature development, the objective was to empower procurement officers to initiate orders on behalf of various departments. A critical requirement was to prevent these orders from appearing on departmental dashboards until formally approved by the respective department manager.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks:&lt;/strong&gt; Architectural decision&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option 1: Decentralised Filtering:&lt;/strong&gt; Modify every single query that retrieves orders across the application. This approach presented a significant risk of identifying and changing potentially dozens or hundreds of queries that would be time-consuming; the likelihood of missing a critical query or introducing subtle bugs was significant, and leading to future changes to data visibility logic requiring similar widespread modifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option 2: Centralised Interception (Chosen):&lt;/strong&gt; Leverage Mongoose middleware to intercept all data retrieval operations. This promised a more robust and maintainable solution by centralising the logic for filtering unapproved orders at the data layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Actions: Filter out unapproved orders&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To facilitate the filtering, I needed a mechanism to mark orders that were pending approval explicitly. We added a new field, &lt;code&gt;activeAction&lt;/code&gt;, to our &lt;code&gt;orderSchema&lt;/code&gt;
&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.amazonaws.com%2Fuploads%2Farticles%2F2tqz6w3q2agktrjxezrp.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%2F2tqz6w3q2agktrjxezrp.png" alt="Schema" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The core of our solution lies in a &lt;code&gt;pre-find&lt;/code&gt; middleware hook. This hook executes automatically before &lt;em&gt;any&lt;/em&gt; &lt;code&gt;find&lt;/code&gt; operation (including &lt;code&gt;findOne&lt;/code&gt;, &lt;code&gt;findById&lt;/code&gt;, etc.) on the &lt;code&gt;Order&lt;/code&gt; model.&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.amazonaws.com%2Fuploads%2Farticles%2F00zav39rvc6vqkkoaski.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%2F00zav39rvc6vqkkoaski.png" alt="Middleware" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clean and Accurate Dashboards:&lt;/strong&gt; Only display approved and relevant order data and eliminating confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralised Logic:&lt;/strong&gt; The core filtering logic resides in a single, well-defined location within the &lt;code&gt;orderSchema&lt;/code&gt;, making it easy to understand, debug, and modify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Development Risk:&lt;/strong&gt; We completely avoided the arduous and error-prone task of modifying numerous &lt;code&gt;find&lt;/code&gt; queries throughout the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable Pattern:&lt;/strong&gt; This approach provides a reusable pattern for managing data visibility based on internal states, applicable to various entities beyond orders.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;How do you use MongoDB middlewares? Share in the comments!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>mongoose</category>
      <category>mongodb</category>
      <category>node</category>
    </item>
    <item>
      <title>Resolving Unexpected Git Hook Changes</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Tue, 08 Jul 2025 13:02:38 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/resolving-unexpected-git-hook-changes-2odo</link>
      <guid>https://dev.to/njabulomajozi/resolving-unexpected-git-hook-changes-2odo</guid>
      <description>&lt;p&gt;&lt;strong&gt;Situation: Unwanted file modifications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recently, after merging a branch, my Pull Request unexpectedly showed numerous file changes that had minor auto-modifications (e.g., “Hello” to 'Hello') due to an active Git hook. These changes weren't part of my task, leading to a noisy and unclear PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task: Isolate &amp;amp; Maintain Focus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Revert unrelated changes&lt;/li&gt;
&lt;li&gt;Keep the PR diff focused on the current task I was working on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Actions: Step-by-step approach&lt;/strong&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%2F2pt0akbjwwmoykk9qqq0.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%2F2pt0akbjwwmoykk9qqq0.png" alt="Step-by-step approach code snippet" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results: Clean PR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restored the affected files to their original state&lt;/li&gt;
&lt;li&gt;My PR was clean and contained only the relevant task changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are your go-to Git commands for managing tricky situations? Share in the comments!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>NextAuth.js over Clerk</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Wed, 24 Apr 2024 09:30:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/nextauthjs-over-clerk-3c8f</link>
      <guid>https://dev.to/njabulomajozi/nextauthjs-over-clerk-3c8f</guid>
      <description>&lt;p&gt;The &lt;a href="https://njabulomajozi.com/insights/auth-with-clerk/" rel="noopener noreferrer"&gt;prior article&lt;/a&gt; examined how Clerk may simplify user authentication for Next.js applications. Clerk provides a handy managed service option, but it's wise to weigh your options before making a choice. Today, we'll examine and contrast Clerk and NextAuth.js, two more well-liked authentication libraries for Next.js, to help you decide which is ideal for your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Next Auth instead of Clerk?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Control and Flexibility&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-Hosted vs. Managed Service:&lt;/strong&gt; NextAuth enables you to fully self-host the authentication flow, giving you more control over user data and security procedures. Conversely, Clerk is a managed service, meaning that its servers hold your user data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization:&lt;/strong&gt; NextAuth provides more flexibility, such as customizing the authentication procedure using callbacks, which are flexible enough to adjust to your unique requirements. The clerk's experience is more preconfigured, but you can still get some flexibility using webhooks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Community and Support:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Larger Community:&lt;/strong&gt; NextAuth benefits from a larger and more active developer community. You'll find more resources, tutorials, and support online if you encounter issues. Clerk, a relatively newer service, might have a smaller support pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Flexibility:&lt;/strong&gt; NextAuth integrates seamlessly with various social providers and other authentication services. You can leverage existing libraries and solutions within your development stack.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Cost:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open-Source vs. Freemium:&lt;/strong&gt; NextAuth is an open-source library with no direct cost for its basic functionalities. Clerk offers a free tier with limitations and paid plans for additional features and user management capabilities.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setting Up Next Auth in Next.js&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install NextAuth&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;next-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure NextAuth&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Server&lt;/p&gt;

&lt;p&gt;NextAuth.js will handle all queries to /api/auth/* (signIn, callback, signOut, etc.) automatically.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NextAuth&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;next-auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GoogleProvider&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-auth/providers/google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;GoogleProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_CLIENT_SECRET&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nc"&gt;NextAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Provider&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SessionProvider&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;next-auth/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SessionProvider&lt;/span&gt; &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SessionProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consumer&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSession&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signOut&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;next-auth/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&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="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      Signed in as &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign out&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    Not signed in &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Sign in&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;NextAuth.js is a compelling alternative to Clerk, offering developers greater control, flexibility, and cost-effectiveness. Its open-source nature, extensive community support, and seamless integration capabilities make it an attractive choice for Next.js applications. Whether you're looking for a self-hosted solution or prefer a managed service, NextAuth.js provides a robust and customizable authentication framework to meet your project's needs.&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>nextauth</category>
      <category>clerk</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Auth with Clerk</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Wed, 17 Apr 2024 15:00:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/auth-with-clerk-408j</link>
      <guid>https://dev.to/njabulomajozi/auth-with-clerk-408j</guid>
      <description>&lt;p&gt;It can be challenging to set up user authentication for web apps. Creating login flows, safely hashing passwords, controlling sessions, and integrating social logins are all part of the traditional process, guaranteeing optimal security. Luckily, there's a more effective method.&lt;/p&gt;

&lt;p&gt;In a recent project, I investigated Clerk, a powerful solution for simplifying user authentication in Next.js applications. Let's explore why Clerk has become my preferred option and how it streamlines development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Clerk Auth?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Forget about the time-consuming back-end configurations. With a wide range of capabilities aimed at improving the security and usability of your application, Clerk gives you the power to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Embeddable UIs:&lt;/strong&gt; Say goodbye to custom login forms! Clerk provides pre-built UI components like SignIn, SignUp, UserButton, and UserProfile that seamlessly integrate into your Next.js and other frontend frameworks supported by Clerk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Clerk offers a comprehensive set of authentication options, including:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multifactor Authentication (MFA):&lt;/strong&gt; Add an extra layer of security with MFA to protect user accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session Management:&lt;/strong&gt; Includes maximum lifetime, inactivity timeout, and multi-session apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social Sign-On:&lt;/strong&gt; Make logging into well-known social media sites like Google, Microsoft, and others easier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email/SMS One-Time Passcodes (OTPs):&lt;/strong&gt; Send verification codes via email or SMS to offer easy log-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Magic Links:&lt;/strong&gt; Simplify the login procedure by using links that, when clicked, provide access.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; Integrate Clerk seamlessly with your preferred development stack:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend SDKs:&lt;/strong&gt; Integrate Clerk with popular frontend frameworks like Next.js, React, React Native/Expo, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend SDKs:&lt;/strong&gt; Leverage Clerk's backend SDKs for Node.js, Go, and other languages.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;More

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Admin Dashboard:&lt;/strong&gt; Manage user authentication and access control from a centralized, secure dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrations:&lt;/strong&gt; Expand your application's functionality by integrating Clerk with other services, such as Firebase, Supabase, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks:&lt;/strong&gt; Stay informed about user activities through real-time notifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bot Detection:&lt;/strong&gt; Clerk helps mitigate brute-force attacks with built-in bot detection mechanisms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;B2B Suite:&lt;/strong&gt; Build secure and scalable authentication experiences for your business-to-business applications.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setting Up Clerk Auth in Next.js&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Install Clerk&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;npm install @clerk/nextjs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure Clerk&lt;/p&gt;

&lt;p&gt;By adding the following environments in .env.local&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=&amp;lt;your clerk public key&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;CLERK_SECRET_KEY=&amp;lt;your clerk secret key&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ClerkProvider&lt;/p&gt;

&lt;p&gt;Provide authentication context to the rest of the application by wrapping around an app, such as root layout.tsx&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ClerkProvider&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="s1"&gt;@clerk/nextjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nx"&gt;JSX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Element&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ClerkProvider&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="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/body&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ClerkProvider&lt;/span&gt;&lt;span class="err"&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Middleware&lt;/p&gt;

&lt;p&gt;Clerk's middleware functionality in the Next.js middleware file handles authentication, protects routes, and ensures that only authenticated users can access them.&lt;br&gt;
&lt;/p&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;authMiddleware&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;@clerk/nextjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/((?!.+&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.[&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;w]+$|_next).*)&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;/(api|trpc)(.*)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure type of auth strategy through a dashboard&lt;/p&gt;

&lt;p&gt;Clerk supports authentication strategies such as password login, social authentication (allowing users to log in using their Google, GitHub, or other social network accounts. This feature enhances the user experience by providing a familiar login process), and more. To those auth strategies, you need to configure it in your Clerk dashboard.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, Clerk supports various authentication strategies, such as password login and social authentication, which can be configured seamlessly through the Clerk dashboard.&lt;/p&gt;

&lt;p&gt;My journey with Clerk Auth has been nothing short of transformative. It's revolutionized how I approach user authentication, offering unparalleled simplicity without compromising security. Clerk isn't just a tool – it's a game-changer for Next.js development.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>clerk</category>
      <category>authentication</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Facebook Introduces Meta AI in WhatsApp</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Mon, 15 Apr 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/facebook-introduces-meta-ai-in-whatsapp-31no</link>
      <guid>https://dev.to/njabulomajozi/facebook-introduces-meta-ai-in-whatsapp-31no</guid>
      <description>&lt;p&gt;Facebook has integrated Meta AI, powered by the Llama model, into WhatsApp, introducing an AI chatbot to enhance user interactions. This integration enables users to engage with AI assistants, offering a new dimension to their messaging experience.&lt;/p&gt;

&lt;p&gt;While you can add Meta AI to group chats, it functions independently. It respects your privacy by not accessing your private conversations, and it doesn't analyze the history of the group chat before joining. It's important to note that this feature is currently in a limited rollout.&lt;/p&gt;

&lt;p&gt;Currently, Meta AI offers basic functionalities. However, the future is promising. We can expect Meta AI to evolve into a powerful tool that can understand and participate in your conversations. This could include features like generating summaries of conversations, analyzing sentiment, or even helping you draft messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; There's more reads at &lt;a href="https://njabulomajozi.com/insights" rel="noopener noreferrer"&gt;My Blog Site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>whatsapp</category>
      <category>facebook</category>
    </item>
    <item>
      <title>AI powered PostgreSQL Test Data Generation Tool (Cloudflare AI Challenge)</title>
      <dc:creator>Njabulo Majozi</dc:creator>
      <pubDate>Sun, 14 Apr 2024 16:07:56 +0000</pubDate>
      <link>https://dev.to/njabulomajozi/ai-powered-postgresql-test-data-generation-tool-cloudflare-ai-challenge-4572</link>
      <guid>https://dev.to/njabulomajozi/ai-powered-postgresql-test-data-generation-tool-cloudflare-ai-challenge-4572</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/devteam/join-us-for-the-cloudflare-ai-challenge-3000-in-prizes-5f99"&gt;Cloudflare AI Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a serverless application using Cloudflare Workers and Hono, a lightweight web framework for Cloudflare Workers. The application is designed to generate steps for inserting random data into a PostgreSQL database and then convert those steps into SQL queries. This is achieved by leveraging Cloudflare's AI models to understand and generate natural language instructions, which are then converted into SQL commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1az4k32t42off1nu8esz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1az4k32t42off1nu8esz.png" alt="Image description" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/njabulomajozi/retriedge"&gt;REPO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core functionality lies in the &lt;code&gt;generate-data&lt;/code&gt; endpoint:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extracting Schema:&lt;/strong&gt; It retrieves the user-provided schema definition from the request body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initializing AI Models:&lt;/strong&gt; It creates instances of two AI models:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@hf/thebloke/deepseek-coder-6.7b-base-awq&lt;/code&gt;: This model understands natural language instructions and generates the steps in human-readable format.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@cf/defog/sqlcoder-7b-2&lt;/code&gt;: This model takes the steps and schema definition, translating them into corresponding SQL code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompting the Models&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The first model receives a prompt explaining the desired outcome and the provided schema.&lt;/li&gt;
&lt;li&gt;The second model receives the generated steps and the schema definition, combining the information for SQL generation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returning Data:&lt;/strong&gt; The function returns a JSON response containing the generated steps and the corresponding SQL code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Building this application involved several steps, from understanding the requirements to implementing the solution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understanding Cloudflare Workers:&lt;/strong&gt; I started by researching how to use Cloudflare Workers and Hono for serverless applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exploring AI Models:&lt;/strong&gt; I explored Cloudflare's AI models to find one that could generate natural language instructions based on a given schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration and Orchestration:&lt;/strong&gt; I implemented the logic to process the generated instructions and convert them into SQL queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multiple Models and/or Triple Task Types&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multiple Models&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application demonstrates multiple AI models from Cloudflare's AI platform. The first model, &lt;code&gt;@hf/thebloke/deepseek-coder-6.7b-base-awq&lt;/code&gt;, generates natural language steps for data insertion. The second model, &lt;code&gt;@cf/defog/sqlcoder-7b-2&lt;/code&gt;, converts these steps into SQL queries. This showcases the flexibility and power of Cloudflare's AI platform in generating complex content based on simple prompts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Triple Task Types&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application performs three main tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Generation&lt;/strong&gt;: It generates natural language steps for inserting data into a PostgreSQL database based on a given schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL Query Generation&lt;/strong&gt;: It converts the generated steps into SQL queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Endpoint&lt;/strong&gt;: It exposes an API endpoint (&lt;code&gt;/generate-data&lt;/code&gt;) that accepts a schema and returns the generated steps and SQL queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Challenges:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Coordinating communication between the two LLMs.&lt;/li&gt;
&lt;li&gt;Prompts designs.&lt;/li&gt;
&lt;li&gt;Ensuring the generated SQL scripts are functional and adhere to the DDL and data constraints.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What I'm Proud Of&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The ability to combine multiple LLMs to achieve a complex task like test data generation for databases.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Experiment with different LLM combinations for improved performance.&lt;/li&gt;
&lt;li&gt;Integrate user feedback to refine the generated test data scripts.&lt;/li&gt;
&lt;li&gt;Local LLMs integration&lt;/li&gt;
&lt;li&gt;Use LangChain SQL agent to retrieve database DDLs&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>devchallenge</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
