<?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: Afaq Shahid Khan</title>
    <description>The latest articles on DEV Community by Afaq Shahid Khan (@afaq_shahid).</description>
    <link>https://dev.to/afaq_shahid</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%2F1505316%2F51d45ab3-6db0-4211-8e4b-8fc68a697ecf.png</url>
      <title>DEV Community: Afaq Shahid Khan</title>
      <link>https://dev.to/afaq_shahid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/afaq_shahid"/>
    <language>en</language>
    <item>
      <title>Implementing Tap Payments in a SaaS Subscription System (Node.js + Express + Sequelize)</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Fri, 19 Dec 2025 14:36:57 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/implementing-tap-payments-in-a-saas-subscription-system-nodejs-express-sequelize-2k2l</link>
      <guid>https://dev.to/afaq_shahid/implementing-tap-payments-in-a-saas-subscription-system-nodejs-express-sequelize-2k2l</guid>
      <description>&lt;p&gt;When building a SaaS product with paid plans, payment handling is never just about charging a card. You need &lt;strong&gt;subscriptions, renewals, upgrades, proration, invoices, webhooks, and failure handling&lt;/strong&gt; — all working reliably.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk through how to integrate &lt;strong&gt;Tap Payments&lt;/strong&gt; into a &lt;strong&gt;Node.js + Express + Sequelize&lt;/strong&gt; backend for a &lt;strong&gt;band-based subscription model&lt;/strong&gt;, using a real production-style architecture.&lt;/p&gt;

&lt;p&gt;This guide focuses on &lt;strong&gt;backend design, security, and reliability&lt;/strong&gt;, not just “making a payment work”.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧱 Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Our system is built around these core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Express (TypeScript)&lt;/strong&gt; — API layer
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequelize&lt;/strong&gt; — relational data modeling
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tap Payments API&lt;/strong&gt; — card payments
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook-based state sync&lt;/strong&gt; — payment truth source
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Band-based licensing&lt;/strong&gt; — users pay per seat band
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High-level flow:&lt;/p&gt;

&lt;p&gt;Client → Backend → Tap Checkout&lt;br&gt;
↘ Webhook → Backend → DB&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


## 📦 Subscription &amp;amp; Payment Data Model

### Subscription (Account-level)

Each account has **exactly one subscription**:

```

ts
Subscription
- accountId
- bandSize
- subscriptionType (trial | paid | suspended)
- startDate / endDate
- unitPrice
- totalAmount
- status


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  SubscriptionPayment (Immutable Ledger)
&lt;/h3&gt;

&lt;p&gt;Every charge creates a &lt;strong&gt;payment record&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
SubscriptionPayment
- subscriptionId
- tapChargeId
- amount
- currency
- paymentMethod (card | invoice)
- status (pending | paid | failed)
- paidAt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key principle:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Subscription state changes ONLY after payment confirmation (via webhook).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔐 Tap API Client (Centralized &amp;amp; Secure)
&lt;/h2&gt;

&lt;p&gt;We isolate Tap API communication in a single client:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
const tapAxios = axios.create({
  baseURL: "https://api.tap.company/v2",
  headers: {
    Authorization: `Bearer ${process.env.TAP_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This avoids:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token leaks&lt;/li&gt;
&lt;li&gt;Duplicate logic&lt;/li&gt;
&lt;li&gt;Inconsistent headers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💳 Creating a Charge (Backend-Controlled)
&lt;/h2&gt;

&lt;p&gt;When a user activates or upgrades a subscription:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create subscription &amp;amp; pending payment in DB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create a Tap charge&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redirect user to Tap checkout&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
export const createTapCharge = async (
  amount: number,
  subscriptionPaymentId: string,
  customer: Customer,
  redirectUrl: string
) =&amp;gt; {
  return tapAxios.post("/charges", {
    amount,
    currency: "OMR",
    customer,
    source: { id: "src_card" },
    redirect: { url: redirectUrl },
    metadata: {
      subscriptionPaymentId,
      type: "subscription",
    },
  });
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Why metadata matters
&lt;/h3&gt;

&lt;p&gt;We store &lt;code&gt;subscriptionPaymentId&lt;/code&gt; inside Tap metadata.&lt;/p&gt;

&lt;p&gt;This allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Webhook → DB mapping&lt;/li&gt;
&lt;li&gt;Idempotent processing&lt;/li&gt;
&lt;li&gt;No guessing which payment belongs to which subscription&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🔁 Redirect-Based Flow (User Experience)
&lt;/h2&gt;

&lt;p&gt;After charge creation, backend returns:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
json
{
  "paymentUrl": "https://tap.company/checkout/...",
  "chargeId": "chg_xxx"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Frontend simply redirects the user.&lt;/p&gt;




&lt;h2&gt;
  
  
  🪝 Webhooks: The Source of Truth
&lt;/h2&gt;

&lt;p&gt;Never trust frontend redirects alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Webhooks?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Users may close the tab&lt;/li&gt;
&lt;li&gt;Network failures happen&lt;/li&gt;
&lt;li&gt;Redirects can be spoofed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Secure Webhook Verification
&lt;/h3&gt;

&lt;p&gt;Tap signs every webhook payload.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
const expectedSignature = crypto
  .createHmac("sha256", TAP_WEBHOOK_SECRET)
  .update(rawBody)
  .digest("hex");


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Only verified requests are processed.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Webhook Processing Logic
&lt;/h2&gt;

&lt;p&gt;On webhook receipt:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify signature&lt;/li&gt;
&lt;li&gt;Extract &lt;code&gt;subscriptionPaymentId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Update payment status&lt;/li&gt;
&lt;li&gt;Update subscription if payment succeeded&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
if (status === "CAPTURED") {
  await payment.update({ status: "paid", paidAt: new Date() });

  await subscription.update({
    status: "active",
    subscriptionType: "paid",
    endDate: nextYear,
  });
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important rule:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Subscription state is updated ONLY inside webhook logic.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📈 Subscription Upgrade with Proration
&lt;/h2&gt;

&lt;p&gt;Upgrades are &lt;strong&gt;prorated&lt;/strong&gt; based on remaining time:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
const remainingYears =
  (subscription.endDate.getTime() - Date.now()) /
  (365.25 * 24 * 60 * 60 * 1000);

const proratedAmount =
  additionalUsers * UNIT_PRICE * remainingYears;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new pending payment&lt;/li&gt;
&lt;li&gt;A new Tap charge&lt;/li&gt;
&lt;li&gt;No disruption to current billing cycle&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📉 Downgrades (Deferred)
&lt;/h2&gt;

&lt;p&gt;Downgrades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply on next renewal&lt;/li&gt;
&lt;li&gt;Do NOT refund automatically&lt;/li&gt;
&lt;li&gt;Prevent abuse near renewal date&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
if (isWithinLockoutWindow(subscription.endDate)) {
  throw new Error("Cannot downgrade near renewal");
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  🧾 Invoice-Based Billing (Enterprise Ready)
&lt;/h2&gt;

&lt;p&gt;For corporate customers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No Tap charge created&lt;/li&gt;
&lt;li&gt;Payment marked as &lt;code&gt;invoice&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Admin manually confirms payment&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
await SubscriptionPayment.create({
  paymentMethod: "invoice",
  status: "paid",
});


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offline billing&lt;/li&gt;
&lt;li&gt;Bank transfers&lt;/li&gt;
&lt;li&gt;Enterprise workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚫 Automatic Suspension for Non-Payment
&lt;/h2&gt;

&lt;p&gt;A scheduled job checks overdue subscriptions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
ts
if (nextPaymentDue &amp;lt; cutoffDate) {
  await subscription.update({ status: "suspended" });
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fair enforcement&lt;/li&gt;
&lt;li&gt;Predictable access control&lt;/li&gt;
&lt;li&gt;No manual intervention&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔐 Authorization &amp;amp; Safety
&lt;/h2&gt;

&lt;p&gt;Critical actions are protected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Only &lt;strong&gt;Account Owners&lt;/strong&gt; can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Activate plans&lt;/li&gt;
&lt;li&gt;Upgrade/downgrade&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;All subscription updates use &lt;strong&gt;DB transactions&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Payments are immutable records&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Key Takeaways
&lt;/h2&gt;

&lt;p&gt;✔ Backend owns all payment logic&lt;br&gt;
✔ Webhooks are the source of truth&lt;br&gt;
✔ Metadata connects payments to business logic&lt;br&gt;
✔ Subscriptions ≠ payments&lt;br&gt;
✔ Design for upgrades, failures, and audits&lt;/p&gt;




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

&lt;p&gt;Tap Payments integrates cleanly into modern SaaS backends &lt;strong&gt;when you treat payments as state machines, not API calls&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’re building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-tenant SaaS&lt;/li&gt;
&lt;li&gt;Seat-based pricing&lt;/li&gt;
&lt;li&gt;Annual subscriptions&lt;/li&gt;
&lt;li&gt;Enterprise billing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture will scale with confidence.&lt;/p&gt;

</description>
      <category>tap</category>
      <category>tappayments</category>
      <category>apigateway</category>
      <category>node</category>
    </item>
    <item>
      <title>🌀 What is React Portal (And Why You Should Use It)</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Sun, 15 Jun 2025 13:06:14 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/what-is-react-portal-and-why-you-should-use-it-2acc</link>
      <guid>https://dev.to/afaq_shahid/what-is-react-portal-and-why-you-should-use-it-2acc</guid>
      <description>&lt;p&gt;&lt;em&gt;By Afaq Shahid Khan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ever built a &lt;strong&gt;modal&lt;/strong&gt;, &lt;strong&gt;toast&lt;/strong&gt;, or &lt;strong&gt;dropdown&lt;/strong&gt; and hit weird issues with &lt;code&gt;z-index&lt;/code&gt;, &lt;code&gt;overflow: hidden&lt;/code&gt;, or elements being clipped unexpectedly?&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;React Portals&lt;/strong&gt; shine! ✨&lt;/p&gt;

&lt;p&gt;Let’s break it down in plain English and see &lt;strong&gt;how and why&lt;/strong&gt; you should start using portals today.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What Is a React Portal?
&lt;/h2&gt;

&lt;p&gt;Normally, React renders components &lt;strong&gt;within the parent DOM tree&lt;/strong&gt;. But sometimes, you want to render something &lt;strong&gt;outside&lt;/strong&gt; of that tree — like a modal that floats on top of everything.&lt;/p&gt;

&lt;p&gt;React Portals let you do exactly that: render components &lt;strong&gt;outside the main DOM hierarchy&lt;/strong&gt;, but still keep them fully connected to React (state, events, etc.).&lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPortal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I'm outside the main DOM tree!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes — that &lt;code&gt;div&lt;/code&gt; will be rendered &lt;strong&gt;as a direct child of &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;&lt;/strong&gt;, no matter where the component lives in your React app.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Build a Toast Notification Using React Portals
&lt;/h2&gt;

&lt;p&gt;Let’s build something practical — a toast popup — and see how portals make it easy.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 1. Create a Toast Component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Toast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPortal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#333&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px 24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;boxShadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 4px 12px rgba(0, 0, 0, 0.15)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;message&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="c1"&gt;// ✅ No need for a custom portal root!&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="nx"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚙️ 2. Use It in Your App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Toast&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;./Toast&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowToast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setShowToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&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;setShowToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// auto-hide after 3s&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="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="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Show Toast&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showToast&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toast&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Hello from a portal!"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Why Use React Portals?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Common UI Problem&lt;/th&gt;
&lt;th&gt;Portals to the Rescue&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Modal hidden behind elements&lt;/td&gt;
&lt;td&gt;✅ Portals escape stacking issues&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;z-index&lt;/code&gt; or &lt;code&gt;overflow: hidden&lt;/code&gt; problems&lt;/td&gt;
&lt;td&gt;✅ Fixed by rendering outside the DOM tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Need to float UI anywhere on the page&lt;/td&gt;
&lt;td&gt;✅ Portals let you place UI wherever you want&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ⚠️ Tips to Use Portals Effectively
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You &lt;strong&gt;don’t need to create&lt;/strong&gt; a special div like &lt;code&gt;#portal-root&lt;/code&gt; — just use &lt;code&gt;document.body&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use portals for things like &lt;strong&gt;modals&lt;/strong&gt;, &lt;strong&gt;tooltips&lt;/strong&gt;, &lt;strong&gt;toasts&lt;/strong&gt;, and &lt;strong&gt;dropdowns&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Don’t overuse them — keep your DOM clean and structured.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;React Portals are like &lt;strong&gt;teleporters 🌀&lt;/strong&gt; — they let your components break free from the regular DOM structure, while still staying connected to React’s state and event system.&lt;/p&gt;

&lt;p&gt;They solve tons of real-world UI problems in a simple way.&lt;/p&gt;

&lt;p&gt;If you’re building floating elements or overlays — &lt;strong&gt;React Portals are your best friend.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;💬 Have a question or want a working demo with modals or tooltips? Drop a comment below!&lt;/p&gt;

&lt;p&gt;❤️ If you found this helpful, leave a like and share it with a fellow dev.&lt;/p&gt;

&lt;p&gt;🖖 Happy coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>ui</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🔁 Reuse React Components with Render Props (Short &amp; Simple)</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Wed, 04 Jun 2025 12:08:08 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/reuse-react-components-with-render-props-short-simple-2hak</link>
      <guid>https://dev.to/afaq_shahid/reuse-react-components-with-render-props-short-simple-2hak</guid>
      <description>&lt;p&gt;In React, &lt;strong&gt;render props&lt;/strong&gt; are a great way to reuse component logic while customizing how things look.&lt;/p&gt;

&lt;p&gt;Let’s say we have &lt;strong&gt;two arrays&lt;/strong&gt; — one for products and one for companies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...];&lt;/span&gt; &lt;span class="c1"&gt;// list of product objects&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;companies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...];&lt;/span&gt; &lt;span class="c1"&gt;// list of company objects&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to render both in different ways, but reuse the same logic for listing and toggling visibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What Is a Render Prop?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;render prop&lt;/strong&gt; is just a prop that takes a function. This function controls how each item is rendered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔧 Reusable &lt;code&gt;List&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;Here’s a simple &lt;code&gt;List&lt;/code&gt; component using a render prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;List&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isCollapsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsCollapsed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displayItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isCollapsed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&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;h2&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;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;displayItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;setIsCollapsed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isCollapsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isCollapsed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Show All&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;Show Less&lt;/span&gt;&lt;span class="dl"&gt;"&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Rendering Products
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Products"&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; - $&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Rendering Companies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Companies"&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;companies&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;companyName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;companyName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; — &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phrase&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Why Use Render Props?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Write once, use anywhere&lt;/li&gt;
&lt;li&gt;Clean separation of logic and UI&lt;/li&gt;
&lt;li&gt;Highly reusable components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it! One component. Two uses. Clean, simple, and powerful.&lt;/p&gt;




&lt;p&gt;💬 Found this helpful? Drop a ❤️ or leave a comment!&lt;/p&gt;

</description>
      <category>renderprops</category>
      <category>react</category>
      <category>reusable</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>How to Do App Routing in Next.js 14</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Mon, 05 Aug 2024 18:01:50 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/how-to-do-app-routing-in-nextjs-14-388a</link>
      <guid>https://dev.to/afaq_shahid/how-to-do-app-routing-in-nextjs-14-388a</guid>
      <description>&lt;p&gt;Next.js 14 continues to enhance its powerful framework, providing developers with robust features for building React applications. One of the key aspects of any web application is routing, and Next.js makes it incredibly simple and efficient. In this post, we'll explore how to set up and use app routing in Next.js 14.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Next.js Routing
&lt;/h2&gt;

&lt;p&gt;Next.js uses a file-based routing system, which means the structure of your &lt;code&gt;pages&lt;/code&gt; directory determines the routes of your application. Each file inside the &lt;code&gt;pages&lt;/code&gt; directory becomes a route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Routing
&lt;/h3&gt;

&lt;p&gt;To create a basic route, you simply need to add a new file to the &lt;code&gt;pages&lt;/code&gt; directory. For example, if you create a file named &lt;code&gt;about.js&lt;/code&gt; inside the &lt;code&gt;pages&lt;/code&gt; directory, it will automatically be available at &lt;code&gt;/about&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/about.js&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;About&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About Us&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is the about page.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dynamic Routing
&lt;/h3&gt;

&lt;p&gt;Next.js also supports dynamic routing using brackets (&lt;code&gt;[]&lt;/code&gt;). This allows you to create routes with dynamic parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/product/[id].js&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;useRouter&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;next/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Product &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, a file named &lt;code&gt;[id].js&lt;/code&gt; inside the &lt;code&gt;pages/product&lt;/code&gt; directory creates a dynamic route that can be accessed via &lt;code&gt;/product/1&lt;/code&gt;, &lt;code&gt;/product/2&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Routes
&lt;/h3&gt;

&lt;p&gt;Nested routes can be created by adding folders inside the &lt;code&gt;pages&lt;/code&gt; directory. Each folder represents a part of the URL path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/blog/index.js&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;Blog&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// pages/blog/[slug].js&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;useRouter&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;next/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog Post: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;slug&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, the &lt;code&gt;/blog&lt;/code&gt; route will render &lt;code&gt;index.js&lt;/code&gt;, and &lt;code&gt;/blog/[slug]&lt;/code&gt; will render &lt;code&gt;[slug].js&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Routes
&lt;/h2&gt;

&lt;p&gt;Next.js also supports API routes, allowing you to create backend endpoints in your application. These are placed in the &lt;code&gt;pages/api&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/api/hello.js&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;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file creates an API endpoint at &lt;code&gt;/api/hello&lt;/code&gt; that responds with a JSON message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing the Router
&lt;/h2&gt;

&lt;p&gt;Next.js 14 allows more customization and advanced routing strategies using the &lt;code&gt;next/router&lt;/code&gt; package. You can programmatically navigate between pages and handle more complex routing scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&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;next/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;navigateToAbout&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/about&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home Page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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="nx"&gt;navigateToAbout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Go to About Page&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;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Next.js 14 continues to simplify and enhance the developer experience with its powerful and flexible routing system. Whether you need static, dynamic, or nested routes, Next.js makes it easy to set up and manage your application's navigation.&lt;/p&gt;

&lt;p&gt;I hope this post helps you get started with routing in Next.js 14. If you have any questions or suggestions, feel free to leave a comment below!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Creating Your First API in a MERN Project</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Fri, 28 Jun 2024 12:25:32 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/creating-your-first-api-in-a-mern-project-4l8k</link>
      <guid>https://dev.to/afaq_shahid/creating-your-first-api-in-a-mern-project-4l8k</guid>
      <description>&lt;p&gt;Hello, fellow developers! 🌟&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through creating your first API in a MERN (MongoDB, Express.js, React, Node.js) project using ES6 modules and modern JavaScript features. This guide is perfect for beginners who want to get started with the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, ensure you have the following installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;npm (Node Package Manager)&lt;/li&gt;
&lt;li&gt;MongoDB (you can use MongoDB Atlas for a cloud-based solution)&lt;/li&gt;
&lt;li&gt;A code editor (VS Code is a popular choice)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up the Project
&lt;/h2&gt;

&lt;p&gt;First, let's create our project directory and set up a new Node.js project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;mern-api
&lt;span class="nb"&gt;cd &lt;/span&gt;mern-api
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the necessary dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express mongoose dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Creating the Server with Express
&lt;/h2&gt;

&lt;p&gt;Create a file named &lt;code&gt;server.js&lt;/code&gt; in your project root and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&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;mongoose&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;mongoose&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;dotenv&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;dotenv&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;userRoute&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;./routes/user.route.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;mongoose&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&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;MONGO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb is connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express is working!!!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRoute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Defining a Model
&lt;/h2&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;models&lt;/code&gt; and inside it, create a file named &lt;code&gt;User.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mongoose&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;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userSchema&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="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Creating a Controller
&lt;/h2&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;controllers&lt;/code&gt; and inside it, create a file named &lt;code&gt;user.controller.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test api is working&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Creating Routes
&lt;/h2&gt;

&lt;p&gt;Create a new directory called &lt;code&gt;routes&lt;/code&gt; and inside it, create a file named &lt;code&gt;user.route.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&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;../controllers/user.controller.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&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="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Integrating Routes in Server
&lt;/h2&gt;

&lt;p&gt;Ensure your &lt;code&gt;server.js&lt;/code&gt; uses the newly created routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&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;express&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;mongoose&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;mongoose&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;dotenv&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;dotenv&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;userRoute&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;./routes/user.route.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;mongoose&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&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;MONGO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb is connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express is working!!!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRoute&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Testing Your API
&lt;/h2&gt;

&lt;p&gt;To test your API, you can use tools like Postman or Insomnia.&lt;/p&gt;

&lt;h3&gt;
  
  
  GET Test Route
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET http://localhost:3000/api/user/test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Congratulations!
&lt;/h2&gt;

&lt;p&gt;You've successfully created your first API in a MERN stack project using modern JavaScript features. This is just the beginning; you can now expand on this by adding more routes, implementing user authentication, and much more.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>mongodb</category>
      <category>express</category>
    </item>
    <item>
      <title>Leveraging Mixins in Ruby on Rails: A Deep Dive</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Wed, 26 Jun 2024 07:13:50 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/leveraging-mixins-in-ruby-on-rails-a-deep-dive-5h0a</link>
      <guid>https://dev.to/afaq_shahid/leveraging-mixins-in-ruby-on-rails-a-deep-dive-5h0a</guid>
      <description>&lt;p&gt;Ruby on Rails is known for its elegance and productivity. One of the powerful tools in Ruby that makes Rails development so flexible and clean is Mixins. In this article, we'll explore what Mixins are, how they work, and how you can use them to keep your Rails codebase DRY (Don't Repeat Yourself).&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Mixins?
&lt;/h3&gt;

&lt;p&gt;Mixins are a way to share reusable code across multiple classes in Ruby. They are modules that can be included in other classes to provide them with additional functionality without using inheritance. This allows you to keep your classes focused and your codebase modular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Mixins?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Code Reusability&lt;/strong&gt;: Mixins allow you to reuse common functionality across different classes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: By moving common methods into modules, you can keep your classes smaller and more focused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoiding Inheritance Pitfalls&lt;/strong&gt;: Instead of relying on complex inheritance hierarchies, you can use Mixins to share behavior across unrelated classes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating a Mixin
&lt;/h3&gt;

&lt;p&gt;Let's start by creating a simple Mixin. Imagine you have several models in your Rails application that need the ability to generate a unique token. Instead of duplicating the token generation code in each model, you can create a Mixin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/concerns/tokenizable.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Tokenizable&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before_create&lt;/span&gt; &lt;span class="ss"&gt;:generate_token&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_token&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using the Mixin
&lt;/h3&gt;

&lt;p&gt;Now that we have our &lt;code&gt;Tokenizable&lt;/code&gt; module, we can include it in any model that needs this functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/user.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Tokenizable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/order.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Tokenizable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ActiveSupport::Concern
&lt;/h3&gt;

&lt;p&gt;In the example above, we used &lt;code&gt;ActiveSupport::Concern&lt;/code&gt; to define our Mixin. &lt;code&gt;ActiveSupport::Concern&lt;/code&gt; makes it easier to write Mixins by providing a structured way to include class methods and instance methods.&lt;/p&gt;

&lt;p&gt;Here's an example that also includes class methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/concerns/tokenizable.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Tokenizable&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before_create&lt;/span&gt; &lt;span class="ss"&gt;:generate_token&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;class_methods&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_by_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;token: &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_token&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SecureRandom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can call &lt;code&gt;User.find_by_token(token)&lt;/code&gt; or &lt;code&gt;Order.find_by_token(token)&lt;/code&gt; thanks to the class method defined in the Mixin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: Timestampable
&lt;/h3&gt;

&lt;p&gt;Let's look at a more practical example. Suppose you want to add a custom timestamp to multiple models in your application. You can create a &lt;code&gt;Timestampable&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/concerns/timestampable.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Timestampable&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before_save&lt;/span&gt; &lt;span class="ss"&gt;:set_custom_timestamp&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_custom_timestamp&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;custom_timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Include this Mixin in your models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/models/post.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Timestampable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# app/models/comment.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comment&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Timestampable&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, both &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;Comment&lt;/code&gt; models will automatically set a custom timestamp before saving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Mixins are a powerful feature in Ruby that can help you keep your Rails codebase clean, DRY, and modular. By encapsulating reusable code in modules and including them in your classes, you can avoid code duplication and manage shared behavior more effectively.&lt;/p&gt;

&lt;p&gt;Whether you're a seasoned Rails developer or just getting started, mastering Mixins will undoubtedly make your code more maintainable and elegant. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Understanding Observers in Ruby on Rails</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Thu, 20 Jun 2024 11:56:23 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/understanding-observers-in-ruby-on-rails-88c</link>
      <guid>https://dev.to/afaq_shahid/understanding-observers-in-ruby-on-rails-88c</guid>
      <description>&lt;p&gt;As your Ruby on Rails application grows, maintaining clean and manageable code becomes increasingly important. One of the powerful yet often underutilized features in Rails is the Observer pattern. Observers allow you to keep your models lean by extracting responsibilities that don't necessarily belong in the model itself. In this article, we'll explore what observers are, when to use them, and how to implement them in your Rails application.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Observers?
&lt;/h3&gt;

&lt;p&gt;Observers in Rails provide a way to respond to lifecycle callbacks outside of your models. They allow you to encapsulate the callback logic in a separate class, promoting cleaner and more modular code. Observers listen for changes to an object and respond to those changes without the object needing to explicitly notify the observer.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Observers
&lt;/h3&gt;

&lt;p&gt;Observers are ideal for situations where you want to decouple the callback logic from your models. Here are a few common use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Analytics:&lt;/strong&gt; Track changes or actions performed on a model without cluttering the model code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notifications:&lt;/strong&gt; Send emails, Slack messages, or other notifications when certain model events occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Jobs:&lt;/strong&gt; Enqueue background jobs in response to model changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Business Logic:&lt;/strong&gt; Implement business rules that should be applied after certain model changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Implementing Observers in Rails
&lt;/h3&gt;

&lt;p&gt;Rails observers are not included in Rails by default anymore, starting from Rails 4. However, you can still use them by including the &lt;code&gt;rails-observers&lt;/code&gt; gem in your Gemfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'rails-observers'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding the gem, run &lt;code&gt;bundle install&lt;/code&gt; to install it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an Observer
&lt;/h3&gt;

&lt;p&gt;Let’s walk through an example of creating an observer. Imagine you have a &lt;code&gt;User&lt;/code&gt; model and you want to send a welcome email whenever a new user is created.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Generate the Observer:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, generate the observer file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rails generate observer User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a file &lt;code&gt;app/models/user_observer.rb&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Define the Observer:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open the generated &lt;code&gt;user_observer.rb&lt;/code&gt; file and define the callback methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserObserver&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Observer&lt;/span&gt;
     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;after_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_later&lt;/span&gt;
     &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;after_create&lt;/code&gt; is a callback method that will be triggered after a new user is created. The &lt;code&gt;UserMailer.welcome_email(user).deliver_later&lt;/code&gt; line enqueues the welcome email to be sent asynchronously.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Register the Observer:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To make Rails aware of the observer, you need to register it. Open &lt;code&gt;config/application.rb&lt;/code&gt; and add the following line inside the &lt;code&gt;class Application &amp;lt; Rails::Application&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;   &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:user_observer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create the Mailer:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you haven't already, generate the mailer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rails generate mailer UserMailer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define the &lt;code&gt;welcome_email&lt;/code&gt; method in &lt;code&gt;app/mailers/user_mailer.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
       &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;subject: &lt;/span&gt;&lt;span class="s1"&gt;'Welcome to My Awesome Site'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="k"&gt;end&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, create a view template for the email in &lt;code&gt;app/views/user_mailer/welcome_email.html.erb&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Using Observers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; By moving callback logic to observers, your models remain focused on their primary responsibility: data persistence and validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability:&lt;/strong&gt; Observers can be reused across different models, promoting DRY (Don't Repeat Yourself) principles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability:&lt;/strong&gt; With a clean separation of callback logic, your codebase becomes easier to maintain and understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Observers are a powerful tool in the Rails ecosystem for maintaining clean and modular code. By decoupling callback logic from your models, you can achieve a more maintainable and scalable codebase. While Rails no longer includes observers by default, the &lt;code&gt;rails-observers&lt;/code&gt; gem makes it easy to integrate this pattern into your application. Use observers to handle logging, notifications, complex business logic, and more, ensuring your models remain lean and focused on their primary responsibilities.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>How to Perform Rake Tasks in Rails</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Fri, 07 Jun 2024 07:55:48 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/how-to-perform-rake-tasks-in-rails-ol2</link>
      <guid>https://dev.to/afaq_shahid/how-to-perform-rake-tasks-in-rails-ol2</guid>
      <description>&lt;p&gt;As a Rails developer, you often need to automate tasks such as database migrations, data seeding, or file management. This is where Rake (Ruby Make) tasks come in handy. In this article, I'll guide you through creating and scheduling Rake tasks in a Rails application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Rake Task?
&lt;/h2&gt;

&lt;p&gt;Rake is a build automation tool written in Ruby. It allows you to define and run tasks using a simple Ruby DSL. In Rails, Rake tasks are commonly used for tasks like database migrations (&lt;code&gt;rake db:migrate&lt;/code&gt;), cleaning logs (&lt;code&gt;rake log:clear&lt;/code&gt;), and many other maintenance tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Custom Rake Task
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a custom Rake task. Suppose you want to delete all PDF files in your &lt;code&gt;public/pdfs&lt;/code&gt; directory every night. Here's how you can do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Rake Task
&lt;/h3&gt;

&lt;p&gt;First, create a new Rake task file in the &lt;code&gt;lib/tasks&lt;/code&gt; directory. We'll name it &lt;code&gt;delete_pdfs.rake&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; lib/tasks
&lt;span class="nb"&gt;touch &lt;/span&gt;lib/tasks/delete_pdfs.rake
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;lib/tasks/delete_pdfs.rake&lt;/code&gt; and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lib/tasks/delete_pdfs.rake&lt;/span&gt;
&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:pdf&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Delete all PDFs from public/pdfs and its subdirectories older than midnight"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;delete: :environment&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'fileutils'&lt;/span&gt;

    &lt;span class="n"&gt;pdf_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&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="s1"&gt;'public'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pdfs'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exist?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&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;pdf_directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'**'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*.pdf'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="no"&gt;FileUtils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Deleted &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Directory &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;pdf_directory&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; does not exist"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Run the Rake Task
&lt;/h3&gt;

&lt;p&gt;You can run your new Rake task from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rake pdf:delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will delete all PDF files in the &lt;code&gt;public/pdfs&lt;/code&gt; directory and its subdirectories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling the Rake Task
&lt;/h2&gt;

&lt;p&gt;To run the task automatically at midnight every day, you can use the &lt;code&gt;whenever&lt;/code&gt; gem, which provides a clear syntax for writing and deploying cron jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Add the &lt;code&gt;whenever&lt;/code&gt; Gem
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;whenever&lt;/code&gt; to your &lt;code&gt;Gemfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'whenever'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;bundle install&lt;/code&gt; to install the gem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure &lt;code&gt;whenever&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Initialize &lt;code&gt;whenever&lt;/code&gt; in your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;wheneverize &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a &lt;code&gt;config/schedule.rb&lt;/code&gt; file. Open this file and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/schedule.rb&lt;/span&gt;

&lt;span class="c1"&gt;# Set the environment&lt;/span&gt;
&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:environment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"development"&lt;/span&gt; &lt;span class="c1"&gt;# or "production"&lt;/span&gt;

&lt;span class="c1"&gt;# Define the task schedule&lt;/span&gt;
&lt;span class="n"&gt;every&lt;/span&gt; &lt;span class="ss"&gt;:day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;at: &lt;/span&gt;&lt;span class="s1"&gt;'12:00 am'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
   &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Delete pdf files'&lt;/span&gt;
   &lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="s2"&gt;"pdf:delete"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Update Cron Jobs
&lt;/h3&gt;

&lt;p&gt;Update your cron jobs by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;whenever &lt;span class="nt"&gt;--update-crontab&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command writes the schedule defined in &lt;code&gt;config/schedule.rb&lt;/code&gt; to your crontab, ensuring that the task runs at the specified time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Verify the Task
&lt;/h3&gt;

&lt;p&gt;Manually run the task to ensure it works correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rake pdf:delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Rake tasks are a powerful way to automate repetitive tasks in your Rails application. By combining Rake with &lt;code&gt;whenever&lt;/code&gt;, you can schedule these tasks to run automatically, making your workflow more efficient.&lt;/p&gt;

&lt;p&gt;I hope this guide helps you get started with creating and scheduling Rake tasks in your Rails projects. If you have any questions or tips of your own, feel free to share them in the comments below!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rails</category>
      <category>ruby</category>
      <category>programming</category>
    </item>
    <item>
      <title>Supercharging Background Processing with Active Job in Rails</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Wed, 05 Jun 2024 07:40:10 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/supercharging-background-processing-with-active-job-in-rails-2lo</link>
      <guid>https://dev.to/afaq_shahid/supercharging-background-processing-with-active-job-in-rails-2lo</guid>
      <description>&lt;p&gt;Background processing is a crucial part of modern web applications. Tasks like sending emails, processing images, or cleaning up databases often take too long to be handled in real-time during a user’s request-response cycle. This is where background job processing comes into play. In Rails, Active Job provides a unified interface to interact with various queuing backends. This article will walk you through the basics of Active Job and how you can use it to enhance your Rails applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Active Job?
&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%2F8qirha0dgu1ac006cxup.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qirha0dgu1ac006cxup.jpg" alt=" " width="640" height="305"&gt;&lt;/a&gt;&lt;br&gt;
Active Job is a framework for declaring jobs and making them run on a variety of queueing backends. The purpose of Active Job is to ensure that all Rails apps have a job infrastructure in place, regardless of which queueing backend is used. Out of the box, Rails supports several backends including Sidekiq, Resque, Delayed Job, and others.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting Up Active Job
&lt;/h2&gt;

&lt;p&gt;To get started with Active Job, you'll need to set up a queueing backend. For this example, we will use Sidekiq, one of the most popular and efficient background processing libraries for Rails.&lt;/p&gt;

&lt;p&gt;First, add Sidekiq to your Gemfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;bundle install&lt;/code&gt; to install the gem.&lt;/p&gt;

&lt;p&gt;Next, configure Sidekiq in your Rails application. Create a file named &lt;code&gt;sidekiq.yml&lt;/code&gt; in your &lt;code&gt;config&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;:concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="na"&gt;:queues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, update your &lt;code&gt;config/application.rb&lt;/code&gt; to include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;YourAppName&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
    &lt;span class="c1"&gt;# other configurations&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue_adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you’ll need to create a file at &lt;code&gt;config/initializers/sidekiq.rb&lt;/code&gt; to configure Sidekiq with Rails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure_server&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s1"&gt;'redis://localhost:6379/0'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure_client&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s1"&gt;'redis://localhost:6379/0'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Job
&lt;/h2&gt;

&lt;p&gt;Creating a job in Rails is straightforward. You can generate a job using the Rails generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate job Example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a job file in &lt;code&gt;app/jobs/example_job.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Do something later&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can define the tasks you want to be performed in the &lt;code&gt;perform&lt;/code&gt; method. For instance, if you want to send a welcome email to a user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WelcomeEmailJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_now&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enqueuing a Job
&lt;/h2&gt;

&lt;p&gt;To enqueue the job, you simply call the &lt;code&gt;perform_later&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;WelcomeEmailJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the job to the queue, and it will be processed by Sidekiq in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring and Managing Jobs
&lt;/h2&gt;

&lt;p&gt;Sidekiq provides a web interface to monitor and manage your jobs. Add the following to your &lt;code&gt;routes.rb&lt;/code&gt; to mount the Sidekiq web interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'sidekiq/web'&lt;/span&gt;
&lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/sidekiq'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now access the Sidekiq web interface at &lt;code&gt;http://localhost:3000/sidekiq&lt;/code&gt;, where you can see job statistics, retry jobs, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling and Retries
&lt;/h2&gt;

&lt;p&gt;Active Job comes with built-in support for error handling and retries. You can specify the number of retries and the wait time between retries in your job class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WelcomeEmailJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;
  &lt;span class="n"&gt;retry_on&lt;/span&gt; &lt;span class="no"&gt;SomeSpecificError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;wait: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;attempts: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_now&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also define a method to handle cases when retries are exhausted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WelcomeEmailJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_now&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;SomeSpecificError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
    &lt;span class="c1"&gt;# Handle the error (e.g., notify an admin)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Active Job in Rails provides a robust and flexible framework for background processing, allowing you to offload time-consuming tasks and keep your application responsive. By leveraging Sidekiq or other queueing backends, you can ensure your jobs are processed efficiently. Whether you're sending emails, processing images, or performing complex data operations, Active Job can help you manage these tasks seamlessly.&lt;/p&gt;

&lt;p&gt;Start integrating Active Job into your Rails applications today and see the difference in performance and user experience!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rails</category>
      <category>sidekiq</category>
      <category>backend</category>
    </item>
    <item>
      <title>Why You Should Start Your Project in Rails 7: Simplicity and Speed</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Thu, 30 May 2024 06:47:54 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/why-you-should-start-your-project-in-rails-7-simplicity-and-speed-4dpe</link>
      <guid>https://dev.to/afaq_shahid/why-you-should-start-your-project-in-rails-7-simplicity-and-speed-4dpe</guid>
      <description>&lt;p&gt;Hi this is Afaq Shahid and today we will learn that how fast, easy and effective Rails 7 is, so let's get started.&lt;br&gt;
Choosing the right framework is crucial for any new project, and Rails 7 stands out for its simplicity and speed. Here’s why it’s the ideal choice for modern web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Streamlined Development with Hotwire&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rails 7 integrates Hotwire, which combines Turbo and Stimulus to simplify building interactive applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turbo&lt;/strong&gt;: Enhances speed and responsiveness by using partial page updates instead of full reloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stimulus&lt;/strong&gt;: Adds lightweight JavaScript behaviors to HTML, reducing the need for extensive front-end code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Hotwire, you can easily create real-time features like live updates and notifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Improved Performance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rails 7 offers several performance enhancements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimized View Rendering&lt;/strong&gt;: Faster HTML generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Database Queries&lt;/strong&gt;: Improved Active Record for quicker data handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements ensure your applications run smoothly and handle more traffic efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Simplified Front-End Development&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rails 7 simplifies front-end development with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Import Maps&lt;/strong&gt;: Manage JavaScript dependencies directly from HTML, eliminating the need for complex bundling tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Node.js Required&lt;/strong&gt;: Develop modern web applications without a Node.js runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes setup and maintenance easier, letting you focus on building features.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Enhanced Developer Experience&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rails 7 continues to prioritize a great developer experience with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less Boilerplate&lt;/strong&gt;: Improved conventions reduce the code you need to write.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Error Messages&lt;/strong&gt;: More informative errors speed up debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Testing&lt;/strong&gt;: Faster and easier test setups.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These enhancements make development faster and more enjoyable.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Robust Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rails 7 maintains strong security with built-in protections against common vulnerabilities and introduces encrypted attributes to secure sensitive data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Rails 7 combines simplicity, speed, and security, making it an excellent choice for new projects. With Hotwire for real-time features, performance optimizations, simplified front-end development, and an enhanced developer experience, Rails 7 helps you build fast, efficient, and secure web applications. Start your next project with Rails 7 to leverage these powerful advantages.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rails</category>
      <category>security</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Callbacks in Rails: Enhancing Model Interactions and Lifecycle Management</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Tue, 28 May 2024 19:12:37 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/understanding-callbacks-in-rails-enhancing-model-interactions-and-lifecycle-management-3a9f</link>
      <guid>https://dev.to/afaq_shahid/understanding-callbacks-in-rails-enhancing-model-interactions-and-lifecycle-management-3a9f</guid>
      <description>&lt;p&gt;Introduction:&lt;/p&gt;

&lt;p&gt;Callbacks are a fundamental aspect of Rails that allow developers to hook into the lifecycle of ActiveRecord objects and execute custom logic at specific points. In this article, we'll explore the concept of callbacks in Rails, how they work, and how you can leverage them to streamline your model interactions and lifecycle management.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to Callbacks:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Callbacks are methods that are automatically invoked at certain points in an object's lifecycle, such as before or after certain operations (e.g., validation, save, create, update, destroy). Rails provides a wide range of built-in callbacks that cover various aspects of model lifecycle management.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Types of Callbacks:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rails callbacks can be categorized into several types based on when they are triggered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before Callbacks&lt;/strong&gt;: Executed before a certain operation (e.g., before_validation, before_save).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After Callbacks&lt;/strong&gt;: Executed after a certain operation (e.g., after_create, after_update).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Around Callbacks&lt;/strong&gt;: Wrap the execution of a certain operation, allowing custom logic to be executed before and after the operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Common Use Cases:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Callbacks are commonly used to perform tasks such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Validation&lt;/strong&gt;: Ensure data integrity by validating attributes before saving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization&lt;/strong&gt;: Normalize data before saving it to the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Auditing&lt;/strong&gt;: Log changes or perform auditing tasks after certain operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Associations&lt;/strong&gt;: Automatically associate or disassociate related objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Invalidate or update caches when records are modified.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Best Practices:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While callbacks can be powerful, it's essential to use them judiciously and adhere to best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Callbacks Simple&lt;/strong&gt;: Callbacks should be kept simple and focused on a single task to maintain code clarity and avoid unintended side effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Business Logic&lt;/strong&gt;: Avoid placing complex business logic within callbacks, as it can make the code harder to understand and maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Callback Logic&lt;/strong&gt;: Write tests to ensure that callback logic behaves as expected and does not introduce regressions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider Alternatives&lt;/strong&gt;: In some cases, alternatives such as service objects or state machines may be more appropriate than callbacks for managing complex interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at a simple example of using callbacks in a Rails model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;before_save&lt;/span&gt; &lt;span class="ss"&gt;:normalize_email&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;normalize_email&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;normalize_email&lt;/code&gt; method is invoked before saving a &lt;code&gt;User&lt;/code&gt; record, ensuring that the email is normalized to lowercase. And you can use them in your controller too.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;/p&gt;

&lt;p&gt;Callbacks are a powerful tool in Rails for managing model lifecycle events and executing custom logic at specific points in an object's lifecycle. By understanding how callbacks work and following best practices, you can leverage them effectively to streamline your model interactions and enhance the maintainability of your Rails applications. Experiment with callbacks in your projects and discover the many ways they can simplify your development workflow. Kindly let me know in comment section if you have any query regarding it.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Integrating Tailwind CSS with Your Rails App: A Step-by-Step Guide</title>
      <dc:creator>Afaq Shahid Khan</dc:creator>
      <pubDate>Thu, 23 May 2024 10:01:17 +0000</pubDate>
      <link>https://dev.to/afaq_shahid/integrating-tailwind-css-with-your-rails-app-a-step-by-step-guide-4k93</link>
      <guid>https://dev.to/afaq_shahid/integrating-tailwind-css-with-your-rails-app-a-step-by-step-guide-4k93</guid>
      <description>&lt;p&gt;Introduction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tailwind CSS has gained popularity among developers for its utility-first approach and flexibility. Integrating Tailwind CSS with your Rails application can enhance your frontend development experience, allowing for rapid prototyping and customizable styling. In this article, we'll walk through the steps to integrate Tailwind CSS into your Rails app and unleash its power for building beautiful interfaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Step 1: Install Tailwind CSS&lt;/p&gt;

&lt;p&gt;First, let's install Tailwind CSS using npm. Navigate to your Rails application directory and run the following command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Step 2: Configure Tailwind CSS&lt;/p&gt;

&lt;p&gt;Next, we need to create a Tailwind CSS configuration file. Run the following command to generate the default configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tailwindcss init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;code&gt;tailwind.config.js&lt;/code&gt; file in your project directory. You can customize this file to tweak Tailwind CSS settings according to your project requirements.&lt;/p&gt;

&lt;p&gt;Step 3: Include Tailwind CSS in Your Stylesheets&lt;/p&gt;

&lt;p&gt;Now, let's include Tailwind CSS in your Rails application. You can import Tailwind CSS into your stylesheet using &lt;code&gt;@import&lt;/code&gt; directive. Create a new file &lt;code&gt;app/assets/stylesheets/tailwind.css&lt;/code&gt; and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Configure PostCSS&lt;/p&gt;

&lt;p&gt;To process Tailwind CSS, we need to configure PostCSS. Install PostCSS and Autoprefixer using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;postcss-loader autoprefixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a PostCSS configuration file &lt;code&gt;postcss.config.js&lt;/code&gt; in your project root directory and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;autoprefixer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Update Webpacker Configuration&lt;/p&gt;

&lt;p&gt;We need to update Webpacker configuration to process PostCSS. Open &lt;code&gt;config/webpacker.yml&lt;/code&gt; and add &lt;code&gt;postcss&lt;/code&gt; to the &lt;code&gt;extensions&lt;/code&gt; list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.js&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.css&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.scss&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.sass&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.module.css&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.module.scss&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.module.sass&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.pcss&lt;/span&gt; &lt;span class="c1"&gt;# Add this line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 6: Use Tailwind CSS Classes in Your Views&lt;br&gt;
Now that Tailwind CSS is integrated into your Rails app, you can start using its utility classes in your views. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-500 text-white p-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Welcome to My Rails App with Tailwind CSS!
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tailwindcss</category>
      <category>ruby</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
