<?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>Forem: Navnit Rai</title>
    <description>The latest articles on Forem by Navnit Rai (@navnit73).</description>
    <link>https://forem.com/navnit73</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%2F1802989%2Fec4b75c3-c767-42ae-95de-5d25e7cf8370.jpg</url>
      <title>Forem: Navnit Rai</title>
      <link>https://forem.com/navnit73</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/navnit73"/>
    <language>en</language>
    <item>
      <title>How to Create Passport &amp; Visa Photos at Home (Without Mistakes) – Complete Guide</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Mon, 13 Apr 2026 12:15:47 +0000</pubDate>
      <link>https://forem.com/navnit73/how-to-create-passport-visa-photos-at-home-without-mistakes-complete-guide-3hj8</link>
      <guid>https://forem.com/navnit73/how-to-create-passport-visa-photos-at-home-without-mistakes-complete-guide-3hj8</guid>
      <description>&lt;p&gt;Applying for a passport or visa?&lt;/p&gt;

&lt;p&gt;One of the most common reasons for rejection is &lt;strong&gt;incorrect photo format&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Wrong size, bad background, poor lighting — even small mistakes can delay your application.&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn &lt;strong&gt;how to create a perfect passport or visa photo at home&lt;/strong&gt;, step-by-step — without going to a studio.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Passport Photos Get Rejected
&lt;/h2&gt;

&lt;p&gt;Before creating your photo, understand the common mistakes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Wrong dimensions (size mismatch)&lt;/li&gt;
&lt;li&gt;❌ Improper head position&lt;/li&gt;
&lt;li&gt;❌ Shadows on face or background&lt;/li&gt;
&lt;li&gt;❌ Non-white or uneven background&lt;/li&gt;
&lt;li&gt;❌ Low resolution or blur&lt;/li&gt;
&lt;li&gt;❌ Incorrect facial expression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even a minor issue can lead to &lt;strong&gt;application rejection or delay&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Requirements for a Perfect Passport Photo
&lt;/h2&gt;

&lt;p&gt;Although requirements vary slightly by country, most follow these rules:&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard Guidelines:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Neutral facial expression (no smile)&lt;/li&gt;
&lt;li&gt;Eyes open and clearly visible&lt;/li&gt;
&lt;li&gt;Plain white or light background&lt;/li&gt;
&lt;li&gt;No shadows&lt;/li&gt;
&lt;li&gt;Proper head size (usually 70–80% of image height)&lt;/li&gt;
&lt;li&gt;High resolution (300 DPI preferred)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-Step: Create Passport Photo at Home
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.  Use a Good Camera
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use a smartphone with a decent camera&lt;/li&gt;
&lt;li&gt;Avoid front camera if possible (lower quality)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.  Set Proper Lighting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stand facing natural light (window light works best)&lt;/li&gt;
&lt;li&gt;Avoid harsh shadows&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Background Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use a plain white wall&lt;/li&gt;
&lt;li&gt;Or a clean light-colored background&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.  Maintain Correct Position
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stand straight&lt;/li&gt;
&lt;li&gt;Keep head centered&lt;/li&gt;
&lt;li&gt;Look directly into the camera&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. 📷Take Multiple Shots
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Capture 5–10 photos&lt;/li&gt;
&lt;li&gt;Choose the sharpest and best-lit one&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Use AI Tools to Fix &amp;amp; Format (Recommended)
&lt;/h2&gt;

&lt;p&gt;Manual editing is difficult and error-prone.&lt;/p&gt;

&lt;p&gt;Instead, use an AI tool like:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://pixpassport.com/" rel="noopener noreferrer"&gt;AI passport photo maker for multiple countries&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use PixPassport?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Automatically removes background&lt;/li&gt;
&lt;li&gt;✅ Adjusts head size to match country rules&lt;/li&gt;
&lt;li&gt;✅ Crops to exact passport/visa dimensions&lt;/li&gt;
&lt;li&gt;✅ Supports multiple countries&lt;/li&gt;
&lt;li&gt;✅ Instant download&lt;/li&gt;
&lt;/ul&gt;






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

&lt;/div&gt;



&lt;h2&gt;
  
  
  For US Visa &amp;amp; Passport Photos
&lt;/h2&gt;

&lt;p&gt;If you're applying specifically for the US:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://usvisaphotoai.com/" rel="noopener noreferrer"&gt;Create DS-160 compliant US visa photo online&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Exact US photo size (2x2 inches)&lt;/li&gt;
&lt;li&gt;Correct head ratio&lt;/li&gt;
&lt;li&gt;Compliance with official US guidelines&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd41595lro1gh14jjukp7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd41595lro1gh14jjukp7.jpeg" alt="Person taking a passport photo at home using a smartphone with proper lighting and plain background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffeijkec8jlnfp6ni5duz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffeijkec8jlnfp6ni5duz.jpeg" alt="Example of correct passport photo guidelines showing head position, neutral expression, and white background"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2i5ioxrit5ttjvsc55aj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2i5ioxrit5ttjvsc55aj.jpeg" alt="AI passport photo tool interface demonstrating automatic background removal and photo adjustment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Pro Tips to Avoid Rejection
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✔️ Don’t wear white clothes (blend with background)&lt;/li&gt;
&lt;li&gt;✔️ Avoid glasses (some countries restrict them)&lt;/li&gt;
&lt;li&gt;✔️ Keep hair away from face&lt;/li&gt;
&lt;li&gt;✔️ Use high-quality image (no compression)&lt;/li&gt;
&lt;li&gt;✔️ Always double-check country-specific requirements&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Why AI Tools Are Better Than Photo Studios
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Studio&lt;/th&gt;
&lt;th&gt;AI Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low / Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;Seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accuracy&lt;/td&gt;
&lt;td&gt;Depends&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Convenience&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AI tools like pixpassport make the process &lt;strong&gt;faster, cheaper, and more accurate&lt;/strong&gt;&lt;/p&gt;




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

&lt;p&gt;Creating passport or visa photos at home is now &lt;strong&gt;easier than ever&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With the right setup + AI tools, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save money 💰&lt;/li&gt;
&lt;li&gt;Save time ⏱️&lt;/li&gt;
&lt;li&gt;Avoid rejection &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Try These Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌍 &lt;a href="https://pixpassport.com/" rel="noopener noreferrer"&gt;Passport photo tool for all countries&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🇺🇸 &lt;a href="https://usvisaphotoai.com/" rel="noopener noreferrer"&gt;US visa photo maker (DS-160 ready)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Have Questions?
&lt;/h2&gt;

&lt;p&gt;Drop them in the comments — happy to help! &lt;/p&gt;




&lt;h1&gt;
  
  
  AI #WebDevelopment #SaaS #PassportPhoto #Visa #IndieHacker #Startup #BuildInPublic #SEO
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>US Visa Photo Rejected? Here’s How USVisaPhotoAI Solves It Instantly</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Sat, 04 Apr 2026 05:29:56 +0000</pubDate>
      <link>https://forem.com/navnit73/us-visa-photo-rejected-heres-how-usvisaphotoai-solves-it-instantly-56o6</link>
      <guid>https://forem.com/navnit73/us-visa-photo-rejected-heres-how-usvisaphotoai-solves-it-instantly-56o6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96pq5tq85kjxtky538vc.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%2F96pq5tq85kjxtky538vc.jpg" alt="Original image of user " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxcbxqayrdd1m38nj7ii.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%2Fjxcbxqayrdd1m38nj7ii.jpg" alt="U.S. Passport, DS-160 &amp;amp; Green Card Photos" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3sabgx3d9kwxjyhqcnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3sabgx3d9kwxjyhqcnu.png" width="750" height="750"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ What “Full Compliance” Means
&lt;/h3&gt;

&lt;p&gt;Your photo is automatically checked against all critical rules, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Head Size Accuracy&lt;/strong&gt; (50%–69% of image height)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eye Position Alignment&lt;/strong&gt; (correct vertical placement)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neutral Expression&lt;/strong&gt; (no smiling, no exaggerated expressions)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Straight Head Position&lt;/strong&gt; (no tilt or rotation)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain White Background&lt;/strong&gt; (no patterns, shadows, or objects)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proper Lighting&lt;/strong&gt; (even exposure, no harsh shadows)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Resolution &amp;amp; Clarity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correct Framing &amp;amp; Centering&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Obstructions&lt;/strong&gt; (glasses glare, shadows, accessories issues)
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  US Visa Photo Rejected? Here’s How USVisaPhotoAI Solves It Instantly
&lt;/h1&gt;

&lt;p&gt;Applying for a U.S. visa, passport, or DV Lottery can be stressful — but one of the most common reasons for rejection is something surprisingly simple: &lt;strong&gt;your photo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every year, thousands of applicants get rejected due to incorrect photo size, wrong background, improper head positioning, or even subtle issues like facial expression. Most people don’t even realize their photo is non-compliant until it’s too late.&lt;/p&gt;

&lt;p&gt;That’s exactly the problem &lt;strong&gt;USVisaPhotoAI&lt;/strong&gt; is built to solve.&lt;/p&gt;

&lt;p&gt;👉 Try it now: &lt;a href="https://www.usvisaphotoai.pro/" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚨 The Real Problem with U.S. Visa Photos
&lt;/h2&gt;

&lt;p&gt;The U.S. Department of State has strict requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head size must be between 50%–69% of image height
&lt;/li&gt;
&lt;li&gt;Eyes must be positioned correctly
&lt;/li&gt;
&lt;li&gt;Neutral expression (no smile)
&lt;/li&gt;
&lt;li&gt;Plain white background
&lt;/li&gt;
&lt;li&gt;No shadows or tilts
&lt;/li&gt;
&lt;li&gt;Proper lighting and resolution
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even a small mistake can lead to rejection.&lt;/p&gt;

&lt;p&gt;Traditional tools only help with cropping — they don’t &lt;strong&gt;validate compliance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 Validate your photo instantly:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/photo-validator" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/photo-validator&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 What Makes USVisaPhotoAI Different?
&lt;/h2&gt;

&lt;p&gt;Unlike basic photo tools, &lt;strong&gt;USVisaPhotoAI&lt;/strong&gt; uses AI to analyze your image across &lt;strong&gt;9 critical compliance parameters&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Advanced AI Checks Include:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Head size accuracy
&lt;/li&gt;
&lt;li&gt;Eye position alignment
&lt;/li&gt;
&lt;li&gt;Face orientation (no tilt)
&lt;/li&gt;
&lt;li&gt;Background detection
&lt;/li&gt;
&lt;li&gt;Lighting &amp;amp; shadow analysis
&lt;/li&gt;
&lt;li&gt;Expression validation (no smiling)
&lt;/li&gt;
&lt;li&gt;Image resolution &amp;amp; quality
&lt;/li&gt;
&lt;li&gt;Centering &amp;amp; framing
&lt;/li&gt;
&lt;li&gt;Cropping compliance
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get instant feedback — not guesswork.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Built for Every U.S. Photo Requirement
&lt;/h2&gt;

&lt;p&gt;Whether you're applying for a visa, green card, or lottery, the tool is tailored for all major use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  🇺🇸 DV Lottery Photo (2027 Entry)
&lt;/h3&gt;

&lt;p&gt;Generate and validate photos specifically for the Diversity Visa program:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/dv-lottery-photo-2027" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/dv-lottery-photo-2027&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🛂 U.S. Passport Photo
&lt;/h3&gt;

&lt;p&gt;Ensure your passport photo meets official standards:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/us-passport-photo" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/us-passport-photo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💳 Green Card Photo
&lt;/h3&gt;

&lt;p&gt;Avoid delays in your Green Card application:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/green-card-photo" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/green-card-photo&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Why People Love USVisaPhotoAI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant Results&lt;/strong&gt; — No waiting, no manual checks
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beginner Friendly&lt;/strong&gt; — Upload and get results in seconds
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accurate AI Validation&lt;/strong&gt; — Goes beyond simple cropping tools
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saves Time &amp;amp; Money&lt;/strong&gt; — Avoid rejections and reapplications
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works Online&lt;/strong&gt; — No software installation needed
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ❌ Common Mistakes This Tool Helps You Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Slight head tilt (often unnoticed)
&lt;/li&gt;
&lt;li&gt;Incorrect head size after cropping
&lt;/li&gt;
&lt;li&gt;Poor lighting or shadows
&lt;/li&gt;
&lt;li&gt;Smiling or non-neutral expression
&lt;/li&gt;
&lt;li&gt;Background not fully white
&lt;/li&gt;
&lt;li&gt;Face not centered
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most people think their photo is fine — until it's rejected. This tool eliminates that risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Who Should Use This?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DV Lottery applicants
&lt;/li&gt;
&lt;li&gt;U.S. visa applicants (DS-160)
&lt;/li&gt;
&lt;li&gt;Passport applicants
&lt;/li&gt;
&lt;li&gt;Immigration &amp;amp; Green Card applicants
&lt;/li&gt;
&lt;li&gt;Developers building visa tools (API potential)
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Getting your U.S. visa photo right shouldn’t be complicated — but strict rules make it easy to fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;USVisaPhotoAI simplifies everything&lt;/strong&gt; by giving you instant, AI-powered validation so you can submit your application with confidence.&lt;/p&gt;

&lt;p&gt;👉 Start now and check your photo:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/photo-validator" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/photo-validator&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;👉 Or explore all tools:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/" rel="noopener noreferrer"&gt;https://www.usvisaphotoai.pro/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Stop guessing. Start validating.&lt;/p&gt;

</description>
      <category>ds160</category>
      <category>visaphoto</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Built an AI Tool to Generate US Visa Photos (And Why Most Photos Fail)</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Wed, 01 Apr 2026 08:22:43 +0000</pubDate>
      <link>https://forem.com/navnit73/how-i-built-an-ai-tool-to-generate-us-visa-photos-and-why-most-photos-fail-1797</link>
      <guid>https://forem.com/navnit73/how-i-built-an-ai-tool-to-generate-us-visa-photos-and-why-most-photos-fail-1797</guid>
      <description>&lt;h1&gt;
  
  
  Why Most US Visa Photos Get Rejected (And How I Solved It with AI)
&lt;/h1&gt;

&lt;p&gt;While working on a visa-related project, I noticed something surprising:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Most users fail at something as simple as uploading a correct visa photo.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And this small mistake?&lt;br&gt;&lt;br&gt;
It leads to &lt;strong&gt;delays, rejections, and frustration.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ The Problem: Visa Photo Requirements Are Brutal
&lt;/h2&gt;

&lt;p&gt;If you’ve ever filled the &lt;strong&gt;DS-160 form&lt;/strong&gt;, you already know:&lt;/p&gt;

&lt;p&gt;The photo requirements are extremely strict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📏 600x600 pixels (exact)&lt;/li&gt;
&lt;li&gt;⚪ Pure white background&lt;/li&gt;
&lt;li&gt;🙂 Neutral expression&lt;/li&gt;
&lt;li&gt;📐 Proper face alignment&lt;/li&gt;
&lt;li&gt;🌗 No shadows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds simple… right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not really.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🤦 What Users Actually Upload
&lt;/h2&gt;

&lt;p&gt;From real user uploads, I saw patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🤳 Selfies taken from phone cameras
&lt;/li&gt;
&lt;li&gt;🔄 Tilted or rotated faces
&lt;/li&gt;
&lt;li&gt;🎨 Colored or messy backgrounds
&lt;/li&gt;
&lt;li&gt;🌑 Shadows on face or wall
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 These mistakes are super common.&lt;/p&gt;

&lt;p&gt;And guess what?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❗ Even a small misalignment = &lt;strong&gt;Photo rejection&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚠️ The Real Impact
&lt;/h2&gt;

&lt;p&gt;This is not just a UX issue.&lt;/p&gt;

&lt;p&gt;It creates real problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Visa application delays
&lt;/li&gt;
&lt;li&gt;❌ Re-upload frustration
&lt;/li&gt;
&lt;li&gt;❌ Confusion about requirements
&lt;/li&gt;
&lt;li&gt;❌ Drop-offs during payment
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers building in this space →&lt;br&gt;&lt;br&gt;
👉 &lt;strong&gt;This is a hidden conversion killer.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The Solution: Automating It with AI
&lt;/h2&gt;

&lt;p&gt;Instead of expecting users to “figure it out”…&lt;/p&gt;

&lt;p&gt;I built a tool that does everything automatically:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 What It Does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🧠 Detects face using AI
&lt;/li&gt;
&lt;li&gt;📐 Fixes head alignment
&lt;/li&gt;
&lt;li&gt;⚪ Removes &amp;amp; replaces background
&lt;/li&gt;
&lt;li&gt;📏 Resizes to exact 600x600 format
&lt;/li&gt;
&lt;li&gt;✅ Makes it compliant with US visa rules
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 No manual editing needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Try It Yourself
&lt;/h2&gt;

&lt;p&gt;I turned this into a simple SaaS tool:&lt;br&gt;
&lt;a href="https://www.usvisaphotoai.pro/" rel="noopener noreferrer"&gt;If you’ve ever struggled with DS-160 photo requirements,&lt;br&gt;
you can now solve it using an AI usvisaphotoai.pro tool.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upload your photo → get a compliant visa photo instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Key Insight for Builders
&lt;/h2&gt;

&lt;p&gt;If you're building SaaS products:&lt;/p&gt;

&lt;p&gt;👉 Don’t trust users to follow strict rules&lt;br&gt;&lt;br&gt;
👉 Automate compliance instead  &lt;/p&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Users don’t read instructions.&lt;br&gt;&lt;br&gt;
They just want results.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💬 Would Love Your Feedback
&lt;/h2&gt;

&lt;p&gt;If you're working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI tools
&lt;/li&gt;
&lt;li&gt;Image processing
&lt;/li&gt;
&lt;li&gt;SaaS conversions
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 I’d love to hear your thoughts.&lt;/p&gt;

&lt;p&gt;Or roast the product 😄&lt;/p&gt;




&lt;h2&gt;
  
  
  🔖 Tags
&lt;/h2&gt;

&lt;h1&gt;
  
  
  saas #buildinpublic #ai #webdev #startup #indiehackers #nextjs
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Building a Scalable Background Removal API with Python, FastAPI, and Rembg 📸</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Thu, 26 Feb 2026 09:40:00 +0000</pubDate>
      <link>https://forem.com/navnit73/building-a-scalable-background-removal-api-with-python-fastapi-and-rembg-5a3g</link>
      <guid>https://forem.com/navnit73/building-a-scalable-background-removal-api-with-python-fastapi-and-rembg-5a3g</guid>
      <description>&lt;p&gt;Removing backgrounds from images used to require complex Photoshop skills or expensive proprietary APIs. But with the rise of Pre-trained Deep Learning models, we can now build our own production-ready service in minutes.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through a scalable background removal tool I built using &lt;strong&gt;FastAPI&lt;/strong&gt; and &lt;strong&gt;Rembg&lt;/strong&gt;, which is the engine behind my project &lt;a href="https://usvisaphotoai.pro" rel="noopener noreferrer"&gt;USVisaPhotoAI.pro&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 The Tech Stack
&lt;/h2&gt;

&lt;p&gt;To make this service fast and scalable, I chose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.10+&lt;/strong&gt;: For its robust ML ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt;: For high-performance, asynchronous API endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rembg&lt;/strong&gt;: A powerful library based on the U2-Net model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pillow (PIL)&lt;/strong&gt;: For image processing and formatting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uvicorn&lt;/strong&gt;: As a lightning-fast ASGI server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠️ Key Features
&lt;/h2&gt;

&lt;p&gt;Unlike a simple script, this implementation is designed for real-world use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Async Processing&lt;/strong&gt;: Handles multiple requests simultaneously without blocking.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Scalable Architecture&lt;/strong&gt;: Easy to containerize with Docker for Kubernetes or AWS ECS deployment.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Multiple Output Formats&lt;/strong&gt;: Supports returning raw bytes or Base64 encoded strings.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Auto-Optimization&lt;/strong&gt;: Handles image resizing to ensure fast processing for large files.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  📦 Quick Start &amp;amp; Implementation
&lt;/h2&gt;

&lt;p&gt;You can find the full source code and documentation in my repository:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/Navnit73/Rembg_background_remover" rel="noopener noreferrer"&gt;GitHub: Rembg Background Remover&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Logic Snippet
&lt;/h3&gt;

&lt;p&gt;The heart of the API is simple yet powerful:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
from fastapi import FastAPI, UploadFile, File
from rembg import remove
import io
from PIL import Image

app = FastAPI()

@app.post("/remove-bg")
async def remove_background(file: UploadFile = File(...)):
    input_image = await file.read()

    # The Magic Happens Here
    output_image = remove(input_image)

    return StreamingResponse(io.BytesIO(output_image), media_type="image/png")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>machinelearning</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why I Built (and Use) AI to Solve the US Visa Photo Nightmare 📸</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Thu, 26 Feb 2026 09:31:23 +0000</pubDate>
      <link>https://forem.com/navnit73/why-i-built-and-use-ai-to-solve-the-us-visa-photo-nightmare-3cge</link>
      <guid>https://forem.com/navnit73/why-i-built-and-use-ai-to-solve-the-us-visa-photo-nightmare-3cge</guid>
      <description>&lt;p&gt;We’ve all been there. You’re filling out the DS-160 for a US Visa, and you get to the final hurdle: &lt;strong&gt;The Photo Upload.&lt;/strong&gt; You take a selfie against a white-ish wall, upload it, and... &lt;em&gt;Internal Server Error&lt;/em&gt; or &lt;em&gt;Photo Rejected.&lt;/em&gt; The U.S. Department of State has notoriously strict requirements. If your head isn't the right size or the background has a slight shadow, your application can be delayed by weeks.&lt;/p&gt;

&lt;p&gt;In 2026, we shouldn't be driving to a CVS or a professional studio for a $20 digital file. That’s why AI-driven compliance tools are changing the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Challenge: More Than Just a Crop
&lt;/h2&gt;

&lt;p&gt;A US Visa photo isn't just a square image. To pass the automated validators, it must meet these exact specs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Ratio:&lt;/strong&gt; Your head must be between 50% and 69% of the image's total height.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Lighting:&lt;/strong&gt; No shadows on the face or background.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Background:&lt;/strong&gt; Must be a plain, off-white, or white background with no textures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Pixels:&lt;/strong&gt; Exactly 600x600px minimum (up to 1200x1200px).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Doing this manually in Photoshop is a headache. Doing it on your phone is nearly impossible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter US Visa Photo AI
&lt;/h2&gt;

&lt;p&gt;I’ve been working with a tool designed specifically to handle these edge cases using Computer Vision. &lt;strong&gt;&lt;a href="https://usvisaphotoai.pro" rel="noopener noreferrer"&gt;USVisaPhotoAI.pro&lt;/a&gt;&lt;/strong&gt; uses a trained model to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Auto-Detect Landmarks:&lt;/strong&gt; It finds your chin and the top of your head to calculate the perfect ratio.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;AI Background Removal:&lt;/strong&gt; It strips out your messy room and replaces it with a compliant, high-quality white background.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Real-Time Validation:&lt;/strong&gt; It checks for "no glasses" and "neutral expression" before you even pay.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Devs Love This Approach
&lt;/h2&gt;

&lt;p&gt;As developers, we love automation. Instead of the manual "trial and error" of uploading to the government portal, &lt;a href="https://usvisaphotoai.pro" rel="noopener noreferrer"&gt;usvisaphotoai.pro&lt;/a&gt; provides a pre-validated file that is virtually guaranteed to pass. &lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Comparison:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Manual/DIY&lt;/th&gt;
&lt;th&gt;US Visa Photo AI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Success Rate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~40% (First try)&lt;/td&gt;
&lt;td&gt;100% Guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Time Spent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30 mins +&lt;/td&gt;
&lt;td&gt;30 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Equipment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tripod + Lighting&lt;/td&gt;
&lt;td&gt;Your Phone&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;If you're planning your next tech conference in the States or moving for a new role, don't let a $2.00 photo error ruin your $185 visa fee. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give it a try here:&lt;/strong&gt; 👉 &lt;a href="https://usvisaphotoai.pro" rel="noopener noreferrer"&gt;&lt;strong&gt;Get Your Compliant Photo at USVisaPhotoAI.pro&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have you ever had a visa application rejected for a silly reason? Let’s talk about the worst bureaucratic hurdles in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>travel</category>
    </item>
    <item>
      <title>Microfrontend using vuejs</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Wed, 04 Feb 2026 13:55:04 +0000</pubDate>
      <link>https://forem.com/navnit73/microfrontend-using-vuejs-446m</link>
      <guid>https://forem.com/navnit73/microfrontend-using-vuejs-446m</guid>
      <description>&lt;p&gt;In 2026, the "frontend monolith" is becoming a thing of the past for enterprise-scale applications. As teams grow, the ability to deploy features independently—without waiting for a 20-minute build of the entire system—is no longer a luxury; it’s a requirement.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll explore how to build a scalable Microfrontend (MFE) architecture using Vue 3, Vite, and Module Federation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Microfrontends?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Microfrontends bring the microservices philosophy to the browser. Instead of one massive Vue application, you break your UI into smaller, self-contained apps that are composed at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why use them?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent Deployments: Team A can update the "Checkout" module without touching Team B's "Product Catalog."&lt;/li&gt;
&lt;li&gt;Technology Agnostic: While we’re focusing on Vue, different modules could theoretically use different versions of Vue or even different frameworks.&lt;/li&gt;
&lt;li&gt;Faster Build Times: You only build and test the module you changed.
The Tech Stack: Vite + Module Federation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Webpack 5 pioneered Module Federation, in 2026, Vite is the go-to for Vue developers due to its insane speed. We’ll use vite-plugin-federation to bridge the gap.&lt;br&gt;
The Architecture&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Host (The Shell): The main container that handles routing and global state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remote (The Microapp): A standalone Vue app that "exposes" specific components or entire pages.&lt;br&gt;
Step 1: Setting Up the Remote App&lt;br&gt;
Imagine we are building a User Dashboard microfrontend.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the project:&lt;br&gt;
npm create vite@latest dashboard-mfe -- --template vue&lt;br&gt;
cd dashboard-mfe&lt;br&gt;
npm install @originjs/vite-plugin-federation --save-dev&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure vite.config.js:&lt;br&gt;
You need to tell Vite which components to "expose" to the outside world.&lt;br&gt;
import { defineConfig } from 'vite';&lt;br&gt;
import vue from '@vitejs/plugin-vue';&lt;br&gt;
import federation from '@originjs/vite-plugin-federation';&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;export default defineConfig({&lt;br&gt;
  plugins: [&lt;br&gt;
    vue(),&lt;br&gt;
    federation({&lt;br&gt;
      name: 'dashboard_app',&lt;br&gt;
      filename: 'remoteEntry.js',&lt;br&gt;
      exposes: {&lt;br&gt;
        './Dashboard': './src/components/Dashboard.vue',&lt;br&gt;
      },&lt;br&gt;
      shared: ['vue'], // Share Vue to avoid loading it twice&lt;br&gt;
    }),&lt;br&gt;
  ],&lt;br&gt;
  build: {&lt;br&gt;
    target: 'esnext', // Required for module federation&lt;br&gt;
  },&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Step 2: Setting Up the Host (Shell)&lt;br&gt;
The Host is the "parent" app that will consume the Dashboard component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Configure vite.config.js in the Host:&lt;br&gt;
We define where the remote app is located.&lt;br&gt;
federation({&lt;br&gt;
name: 'host_app',&lt;br&gt;
remotes: {&lt;br&gt;
dashboard: '&lt;a href="http://localhost:5001/assets/remoteEntry.js" rel="noopener noreferrer"&gt;http://localhost:5001/assets/remoteEntry.js&lt;/a&gt;',&lt;br&gt;
},&lt;br&gt;
shared: ['vue'],&lt;br&gt;
})&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consume the Remote Component:&lt;br&gt;
In your Host's Vue files, you can now import the remote component as if it were local.&lt;br&gt;
&amp;lt;br&amp;gt;
import { defineAsyncComponent } from &amp;amp;#39;vue&amp;amp;#39;;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;// Lazy load the remote component&amp;lt;br&amp;gt;
const RemoteDashboard = defineAsyncComponent(() =&amp;amp;gt; import(&amp;amp;#39;dashboard/Dashboard&amp;amp;#39;));&amp;lt;br&amp;gt;
&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
  &lt;br&gt;
    Shell Navigation&lt;br&gt;
    &lt;br&gt;
  &lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Best Practices for 2026&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;State Management (Pinia)
Don't try to share a single global Pinia store across all MFEs. This creates tight coupling. Instead:

&lt;ul&gt;
&lt;li&gt;Remotes should have their own local stores.&lt;/li&gt;
&lt;li&gt;Communication should happen via Custom Events or a lightweight Event Bus.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Versioning and Deployment&lt;br&gt;
Always use a Blue/Green deployment strategy for your remotes. Since the Host fetches the remoteEntry.js at runtime, a broken remote can take down the UI. Use Error Boundaries in Vue to catch loading failures:&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;br&gt;
  Loading Dashboard...&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CSS Isolation&lt;br&gt;
Use CSS Modules or Scoped Styles () religiously. In a microfrontend world, a global .btn class in your Auth MFE can accidentally ruin the styling of your Dashboard MFE.&amp;lt;br&amp;gt;
Summary Table: Vite vs. Single-SPA&amp;lt;br&amp;gt;
| Feature | Vite + Module Federation | Single-SPA |&amp;lt;br&amp;gt;
|---|---|---|&amp;lt;br&amp;gt;
| Ease of Use | High (Plugin-based) | Medium (High Boilerplate) |&amp;lt;br&amp;gt;
| Performance | Native ESM (Fastest) | SystemJS (Slight Overhead) |&amp;lt;br&amp;gt;
| Best For | Pure Vue/Modern Stacks | Heterogeneous Stacks (Angular + Vue + React) |&amp;lt;br&amp;gt;
Microfrontends aren&amp;amp;#39;t a silver bullet—they add operational complexity. But for large teams, the trade-off in developer velocity is almost always worth it.&amp;lt;br&amp;gt;
Would you like me to generate a complete boilerplate repository structure for this setup?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>tutorial</category>
      <category>vue</category>
    </item>
    <item>
      <title>How to Create a Modern Chatbot Component in Vue.js Using Vuetify and CSS</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Fri, 30 Jan 2026 05:36:43 +0000</pubDate>
      <link>https://forem.com/navnit73/how-to-create-a-modern-chatbot-component-in-vuejs-using-vuetify-and-css-1m1e</link>
      <guid>https://forem.com/navnit73/how-to-create-a-modern-chatbot-component-in-vuejs-using-vuetify-and-css-1m1e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fges0qoccz5k0ceaoy6qf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fges0qoccz5k0ceaoy6qf.png" alt=" " width="523" height="887"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building a chatbot UI is no longer just a “nice to have” feature — it’s becoming a core part of modern web applications. Whether you’re creating a customer support bot, appointment booking assistant, or AI chat interface, Vue.js combined with Vuetify makes the job clean, scalable, and visually polished.&lt;/p&gt;

&lt;p&gt;In this post, you’ll learn how to create a fully functional chatbot component in Vue.js using Vuetify and custom CSS, inspired by popular messaging apps like WhatsApp.&lt;/p&gt;

&lt;p&gt;What You’ll Build&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you’ll have a chatbot that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp-style chat UI&lt;/li&gt;
&lt;li&gt;AI &amp;amp; user message bubbles&lt;/li&gt;
&lt;li&gt;Typing indicator animation&lt;/li&gt;
&lt;li&gt;Quick reply buttons&lt;/li&gt;
&lt;li&gt;Emoji picker&lt;/li&gt;
&lt;li&gt;API integration using Axios&lt;/li&gt;
&lt;li&gt;Auto-scrolling chat history&lt;/li&gt;
&lt;li&gt;Modular widget actions (Booking / Ticket widgets)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tech Stack Used&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vue.js (Options API)&lt;/li&gt;
&lt;li&gt;Vuetify (Material UI for Vue)&lt;/li&gt;
&lt;li&gt;Axios (API calls)&lt;/li&gt;
&lt;li&gt;CSS Animations&lt;/li&gt;
&lt;li&gt;REST API (Chat backend)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chatbot Component Structure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At a high level, the chatbot UI is divided into three main sections:&lt;/li&gt;
&lt;li&gt;Header – Bot name, avatar, online status&lt;/li&gt;
&lt;li&gt;Messages Area – Chat history, typing animation, quick replies&lt;/li&gt;
&lt;li&gt;Input Area – Message input, emoji picker, send button
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ChatbotCard
 ├── Header
 ├── MessageContainer
 │    ├── AI Messages
 │    ├── User Messages
 │    ├── Typing Indicator
 │    └── Widgets
 └── Input Area

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Creating the Chatbot Layout (Vuetify Card)
&lt;/h2&gt;

&lt;p&gt;We use a v-card as the chatbot container to give it a clean, app-like feel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;v-card class="chatbot-container d-flex flex-column" height="90vh" rounded="xl"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;This makes the chatbot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsive&lt;/li&gt;
&lt;li&gt;Scrollable&lt;/li&gt;
&lt;li&gt;Mobile-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Chat Header (Custom Toolbar)
&lt;/h2&gt;

&lt;p&gt;Instead of using v-toolbar, a custom header gives you full control over design:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Back button&lt;/li&gt;
&lt;li&gt;Bot avatar&lt;/li&gt;
&lt;li&gt;Online status&lt;/li&gt;
&lt;li&gt;Menu icon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is perfect for embedded chatbots or mobile layouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Rendering Chat Messages (AI vs User)
&lt;/h2&gt;

&lt;p&gt;Messages are rendered dynamically using v-for from chat_history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Message Bubble&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div v-if="item.actor === 'ai'" class="ai-message"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User Message Bubble&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div v-if="item.actor === 'user'" class="user-message"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Each message includes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;li&gt;Smooth fade-in animation&lt;/li&gt;
&lt;li&gt;Responsive max width&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Quick Reply Buttons
&lt;/h2&gt;

&lt;p&gt;Quick replies improve UX and reduce typing friction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;v-btn
  v-for="button in item.button"
  @click="handleButtonClick(button)"
&amp;gt;
  {{ button.title }}
&amp;lt;/v-btn&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appointment booking&lt;/li&gt;
&lt;li&gt;FAQs&lt;/li&gt;
&lt;li&gt;Menu-based navigation&lt;/li&gt;
&lt;li&gt;AI actions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Action-Based Widgets (Advanced Feature)
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
Your chatbot supports dynamic UI widgets, such as:**&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;BookingWidget v-if="currentAction === 'SHOW_BOOKING_WIDGET'" /&amp;gt;
&amp;lt;TicketWidget v-if="currentAction === 'SHOW_TICKET_WIDGET'" /&amp;gt;

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

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Appointment booking inside chat&lt;/li&gt;
&lt;li&gt;Forms without navigation&lt;/li&gt;
&lt;li&gt;Conversational workflows
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;v-card 
        class="chatbot-container d-flex flex-column" 
        height="90vh"
        elevation="0"
        rounded="xl"
    &amp;gt;
        &amp;lt;!-- Custom Header (no v-toolbar) --&amp;gt;
        &amp;lt;div class="chatbot-header"&amp;gt;
            &amp;lt;div class="d-flex align-center pa-3"&amp;gt;
                &amp;lt;v-btn 
                    icon 
                    variant="text" 
                    size="small"
                    @click="$emit('close')"
                    class="mr-2"
                &amp;gt;
                    &amp;lt;v-icon color="white"&amp;gt;mdi-arrow-left&amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-btn&amp;gt;

                &amp;lt;v-avatar size="40" class="mr-3 bot-avatar"&amp;gt;
                    &amp;lt;v-icon color="white"&amp;gt;mdi-robot-happy&amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-avatar&amp;gt;

                &amp;lt;div class="flex-grow-1"&amp;gt;
                    &amp;lt;div class="text-white font-weight-medium"&amp;gt;QR Buddy Bot&amp;lt;/div&amp;gt;
                    &amp;lt;div class="text-caption" style="color: rgba(255,255,255,0.8);"&amp;gt;
                        &amp;lt;v-icon size="8" color="success" class="mr-1"&amp;gt;mdi-circle&amp;lt;/v-icon&amp;gt;
                        Online
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;

                &amp;lt;v-btn 
                    icon 
                    variant="text" 
                    size="small"
                &amp;gt;
                    &amp;lt;v-icon color="white"&amp;gt;mdi-dots-vertical&amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-btn&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;!-- Chat messages area --&amp;gt;
        &amp;lt;v-card-text class="flex-grow-1 overflow-y-auto pa-3 message-container" ref="messageContainer"&amp;gt;
            &amp;lt;div v-if="isLoading" class="d-flex justify-center align-center fill-height"&amp;gt;
                &amp;lt;div class="text-center"&amp;gt;
                    &amp;lt;v-progress-circular 
                        indeterminate 
                        color="primary" 
                        size="48"
                        width="4"
                    &amp;gt;&amp;lt;/v-progress-circular&amp;gt;
                    &amp;lt;p class="mt-3 text-grey"&amp;gt;Loading chat...&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div v-else&amp;gt;
                &amp;lt;transition-group name="message" tag="div"&amp;gt;
                    &amp;lt;div v-for="(item, index) in chat_history" :key="index" class="mb-2 message-item"&amp;gt;
                        &amp;lt;!-- AI Message --&amp;gt;
                        &amp;lt;div v-if="item.actor === 'ai'" class="d-flex align-start message-fade-in"&amp;gt;
                            &amp;lt;v-avatar class="mr-2 flex-shrink-0" size="32" color="primary"&amp;gt;
                                &amp;lt;v-icon color="white" size="18"&amp;gt;mdi-robot-happy&amp;lt;/v-icon&amp;gt;
                            &amp;lt;/v-avatar&amp;gt;

                            &amp;lt;div class="flex-grow-1" style="max-width: calc(100% - 48px);"&amp;gt;
                                &amp;lt;div class="ai-message"&amp;gt;
                                    &amp;lt;p class="text-body-2 mb-0 message-text"&amp;gt;{{ item.message }}&amp;lt;/p&amp;gt;
                                    &amp;lt;div class="d-flex align-center justify-end mt-1"&amp;gt;
                                        &amp;lt;span class="message-time"&amp;gt;{{ formatTime(item.timestamp) }}&amp;lt;/span&amp;gt;
                                    &amp;lt;/div&amp;gt;
                                &amp;lt;/div&amp;gt;

                                &amp;lt;!-- Quick Reply Buttons --&amp;gt;
                                &amp;lt;div v-if="item.button &amp;amp;&amp;amp; item.button.length" class="d-flex flex-wrap mt-2 gap-2"&amp;gt;
                                    &amp;lt;v-btn
                                        v-for="(button, i) in item.button"
                                        :key="i"
                                        class="quick-reply-btn"
                                        variant="outlined"
                                        size="small"
                                        rounded="xl"
                                        @click="handleButtonClick(button)"
                                        :color="button.color || 'primary'"
                                    &amp;gt;
                                        &amp;lt;v-icon v-if="button.icon" size="16" class="mr-1"&amp;gt;{{ button.icon }}&amp;lt;/v-icon&amp;gt;
                                        {{ button.title }}
                                    &amp;lt;/v-btn&amp;gt;
                                &amp;lt;/div&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;

                        &amp;lt;!-- User Message --&amp;gt;
                        &amp;lt;div v-if="item.actor === 'user'" class="d-flex justify-end message-fade-in"&amp;gt;
                            &amp;lt;div class="user-message"&amp;gt;
                                &amp;lt;p class="text-body-2 text-white mb-0 message-text"&amp;gt;
                                    {{ item.display_text || item.message }}
                                &amp;lt;/p&amp;gt;
                                &amp;lt;div class="d-flex align-center justify-end mt-1"&amp;gt;
                                    &amp;lt;span class="message-time-user"&amp;gt;{{ formatTime(item.timestamp) }}&amp;lt;/span&amp;gt;
                                    &amp;lt;v-icon size="14" color="white" class="ml-1"&amp;gt;mdi-check-all&amp;lt;/v-icon&amp;gt;
                                &amp;lt;/div&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/transition-group&amp;gt;

                &amp;lt;!-- Typing indicator --&amp;gt;
                &amp;lt;div v-if="isTyping" class="d-flex align-start mb-2 message-fade-in"&amp;gt;
                    &amp;lt;v-avatar class="mr-2" size="32" color="primary"&amp;gt;
                        &amp;lt;v-icon color="white" size="18"&amp;gt;mdi-robot-happy&amp;lt;/v-icon&amp;gt;
                    &amp;lt;/v-avatar&amp;gt;
                    &amp;lt;div class="ai-message typing-bubble"&amp;gt;
                        &amp;lt;div class="typing-indicator"&amp;gt;
                            &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                            &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                            &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                        &amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;!-- Widgets --&amp;gt;
            &amp;lt;BookingWidget v-if="currentAction === 'SHOW_BOOKING_WIDGET'" /&amp;gt;
            &amp;lt;TicketWidget v-if="currentAction === 'SHOW_TICKET_WIDGET'" /&amp;gt;
        &amp;lt;/v-card-text&amp;gt;

        &amp;lt;!-- WhatsApp-style Input area --&amp;gt;
        &amp;lt;div class="input-area"&amp;gt;
            &amp;lt;div class="input-container"&amp;gt;
                &amp;lt;!-- Emoji Picker --&amp;gt;
                &amp;lt;v-menu 
                    location="top" 
                    :close-on-content-click="false"
                    offset="8"
                &amp;gt;
                    &amp;lt;template v-slot:activator="{ props }"&amp;gt;
                        &amp;lt;v-btn 
                            v-bind="props" 
                            icon 
                            variant="text" 
                            size="small" 
                            class="emoji-trigger"
                        &amp;gt;
                            &amp;lt;v-icon color="grey-darken-1"&amp;gt;mdi-emoticon-happy-outline&amp;lt;/v-icon&amp;gt;
                        &amp;lt;/v-btn&amp;gt;
                    &amp;lt;/template&amp;gt;

                    &amp;lt;v-card class="emoji-picker" rounded="xl" elevation="8"&amp;gt;
                        &amp;lt;v-card-text class="pa-3"&amp;gt;
                            &amp;lt;div class="text-caption text-grey mb-2 font-weight-medium"&amp;gt;Frequently Used&amp;lt;/div&amp;gt;
                            &amp;lt;div class="emoji-grid"&amp;gt;
                                &amp;lt;button 
                                    v-for="emoji in quickEmojis" 
                                    :key="emoji"
                                    class="emoji-btn"
                                    @click="newMessage += emoji"
                                &amp;gt;
                                    {{ emoji }}
                                &amp;lt;/button&amp;gt;
                            &amp;lt;/div&amp;gt;
                        &amp;lt;/v-card-text&amp;gt;
                    &amp;lt;/v-card&amp;gt;
                &amp;lt;/v-menu&amp;gt;

                &amp;lt;!-- Message Input Field --&amp;gt;
                &amp;lt;div class="message-input-wrapper"&amp;gt;
                    &amp;lt;input
                        v-model="newMessage"
                        type="text"
                        placeholder="Type a message"
                        class="message-input"
                        @keyup.enter="sendMessage"
                    /&amp;gt;
                &amp;lt;/div&amp;gt;

                &amp;lt;!-- Attachment Button (optional) --&amp;gt;
                &amp;lt;v-btn 
                    v-if="!newMessage.trim()"
                    icon 
                    variant="text" 
                    size="small" 
                    class="attachment-btn"
                &amp;gt;
                    &amp;lt;v-icon color="grey-darken-1"&amp;gt;mdi-paperclip&amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-btn&amp;gt;

                &amp;lt;!-- Camera Button (optional) --&amp;gt;
                &amp;lt;v-btn 
                    v-if="!newMessage.trim()"
                    icon 
                    variant="text" 
                    size="small" 
                    class="camera-btn"
                &amp;gt;
                    &amp;lt;v-icon color="grey-darken-1"&amp;gt;mdi-camera&amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-btn&amp;gt;

                &amp;lt;!-- Send/Voice Button --&amp;gt;
                &amp;lt;v-btn 
                    icon
                    size="small"
                    class="send-button"
                    :class="{ 'has-text': newMessage.trim() }"
                    @click="sendMessage"
                    elevation="0"
                &amp;gt;
                    &amp;lt;v-icon color="white" size="20"&amp;gt;
                        {{ newMessage.trim() ? 'mdi-send' : 'mdi-microphone' }}
                    &amp;lt;/v-icon&amp;gt;
                &amp;lt;/v-btn&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/v-card&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import BookingWidget from './BookingWidget.vue';
import TicketWidget from './TicketWidget.vue';
import axios from 'axios';

export default {
    components: {
        BookingWidget,
        TicketWidget
    },
    data() {
        return {
            newMessage: '',
            isLoading: false,
            isTyping: false,
            user_id: 'user_1138',
            chat_history: [
                {
                    actor: 'user',
                    message: 'hi how are you',
                    timestamp: '2025-07-25T05:21:41.636Z'
                },
                {
                    actor: 'ai',
                    type: 'text',
                    message: 'I am doing well, thank you for asking! How are you?',
                    timestamp: '2025-07-25T05:21:42.696Z'
                },
                {
                    actor: 'user',
                    message: 'i need a help',
                    timestamp: '2025-07-25T05:21:52.965Z'
                },
                {
                    actor: 'ai',
                    type: 'text',
                    message: "Okay, I'm here to help! Please tell me what you need help with. The more details you can provide, the better I can assist you.",
                    timestamp: '2025-07-25T05:21:55.172Z'
                },
                {
                    actor: 'user',
                    message: 'i want to book appointment',
                    timestamp: '2025-07-25T05:22:05.565Z'
                },
                {
                    actor: 'ai',
                    type: 'text',
                    message: 'Great! I can help you book an appointment. To get started, I need some information from you. What type of appointment would you like to book?',
                    timestamp: '2025-07-25T05:22:07.368Z',
                    action: 'SHOW_BOOKING_WIDGET',
                    button: [
                        { title: 'Doctor Appointment', payload: 'book_doctor', icon: 'mdi-hospital-box', color: 'primary' },
                        { title: 'Salon Booking', payload: 'book_salon', icon: 'mdi-content-cut', color: 'purple' },
                        { title: 'Service Appointment', payload: 'book_service', icon: 'mdi-wrench', color: 'orange' }
                    ]
                },
                {
                    actor: 'user',
                    message: 'ok thanks for provided me guidence',
                    timestamp: '2025-07-25T05:22:28.668Z'
                },
                {
                    actor: 'ai',
                    type: 'text',
                    message: "You're welcome! Let me know if you have any other questions or need further assistance with anything else.",
                    timestamp: '2025-07-25T05:22:30.356Z'
                }
            ],
            currentAction: null,
            quickEmojis: ['😊', '😂', '❤️', '👍', '🙏', '🎉', '👏', '🔥', '✨', '💯', '🚀', '💪', '😍', '🤔', '👌', '🙌']
        };
    },
    async created() {
        await this.loadData();
    },
    mounted() {
        this.scrollToBottom();
    },
    updated() {
        this.scrollToBottom();
    },
    methods: {
        async loadData() {
            this.isLoading = true;
            try {
                const response = await axios.get(`http://localhost:3005/chat/history`, {
                    params: { user_id: this.user_id }
                });
                this.chat_history = response.data;
            } catch (error) {
                console.error('Error loading chat history:', error);
            } finally {
                this.isLoading = false;
            }
        },
        async sendMessage() {
            const messageText = this.newMessage.trim();
            if (!messageText) return;

            this.chat_history.push({
                actor: 'user',
                message: messageText,
                timestamp: new Date().toISOString()
            });

            this.newMessage = '';
            this.isTyping = true;

            await this.postChatUpdate();

            this.isTyping = false;
        },
        async handleButtonClick(button) {
            this.chat_history.push({
                actor: 'user',
                type: 'payload',
                message: button.payload,
                display_text: button.title,
                timestamp: new Date().toISOString()
            });

            this.isTyping = true;
            await this.postChatUpdate();
            this.isTyping = false;
        },
        async postChatUpdate() {
            try {
                const response = await axios.post('http://localhost:3005/chat', {
                    user_id: 1,
                    chat_history: this.chat_history
                });
                this.chat_history = response.data.chat_history;
                const lastAiMessage = [...this.chat_history].reverse().find((m) =&amp;gt; m.actor === 'ai' &amp;amp;&amp;amp; m.action);
                this.currentAction = lastAiMessage ? lastAiMessage.action : null;
            } catch (error) {
                console.error('Error sending message:', error);
                this.chat_history.push({
                    actor: 'ai',
                    type: 'text',
                    message: "Sorry, I couldn't connect to the server. Please try again later.",
                    timestamp: new Date().toISOString()
                });
            }
        },
        formatTime(timestamp) {
            if (!timestamp) return '';
            const date = new Date(timestamp);
            return date.toLocaleTimeString('en-US', { 
                hour: 'numeric', 
                minute: '2-digit',
                hour12: true 
            });
        },
        scrollToBottom() {
            this.$nextTick(() =&amp;gt; {
                const container = this.$refs.messageContainer;
                if (container) {
                    container.scrollTop = container.scrollHeight;
                }
            });
        }
    }
};
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
* {
    box-sizing: border-box;
}

.chatbot-container {
    background: #f0f2f5;
    position: relative;
    max-width: 100%;
    margin: 0 auto;
}

/* Header Styling */
.chatbot-header {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.bot-avatar {
    background: rgba(255, 255, 255, 0.2) !important;
    backdrop-filter: blur(10px);
}

/* Message Container */
.message-container {
    background: #e5ddd5;
    background-image: 
        url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23d9d9d9' fill-opacity='0.1'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    position: relative;
}

.message-container::-webkit-scrollbar {
    width: 6px;
}

.message-container::-webkit-scrollbar-track {
    background: transparent;
}

.message-container::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.2);
    border-radius: 10px;
}

/* AI Message Bubbles */
.ai-message {
    background: white;
    padding: 8px 12px;
    border-radius: 8px;
    border-top-left-radius: 0;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
    display: inline-block;
    max-width: 100%;
    word-wrap: break-word;
}

/* User Message Bubbles */
.user-message {
    background: #a5a9eb;
    padding: 8px 12px;
    border-radius: 8px;
    border-top-right-radius: 0;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
    display: inline-block;
    max-width: 75%;
    word-wrap: break-word;
    margin-left: auto;
}

.message-text {
    line-height: 1.4;
    color: #303030;
    font-size: 14px;
}

.message-time {
    font-size: 11px;
    color: #0b0000;
    margin-top: 2px;
}

.message-time-user {
    font-size: 11px;
    color: rgb(246, 243, 243);
    margin-top: 2px;
}

/* Quick Reply Buttons */
.quick-reply-btn {
    text-transform: none !important;
    font-weight: 500;
    font-size: 13px;
    height: 32px !important;
    border-width: 1.5px !important;
    transition: all 0.2s ease;
}

.quick-reply-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.gap-2 {
    gap: 8px;
}

/* Typing Indicator */
.typing-bubble {
    padding: 12px 16px;
}

.typing-indicator {
    display: flex;
    align-items: center;
    gap: 4px;
}

.typing-indicator span {
    height: 8px;
    width: 8px;
    background-color: #90949c;
    border-radius: 50%;
    display: inline-block;
    animation: typing 1.4s infinite ease-in-out;
}

.typing-indicator span:nth-child(1) {
    animation-delay: 0s;
}

.typing-indicator span:nth-child(2) {
    animation-delay: 0.2s;
}

.typing-indicator span:nth-child(3) {
    animation-delay: 0.4s;
}

@keyframes typing {
    0%, 60%, 100% {
        transform: translateY(0);
        opacity: 0.5;
    }
    30% {
        transform: translateY(-8px);
        opacity: 1;
    }
}

/* WhatsApp-style Input Area */
.input-area {
    background: #f0f2f5;
    padding: 8px 12px 8px 8px;
    border-top: 1px solid rgba(0, 0, 0, 0.05);
}

.input-container {
    display: flex;
    align-items: center;
    gap: 6px;
    background: white;
    border-radius: 24px;
    padding: 4px 4px 4px 8px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.emoji-trigger, .attachment-btn, .camera-btn {
    min-width: 36px !important;
    width: 36px !important;
    height: 36px !important;
}

.message-input-wrapper {
    flex: 1;
    position: relative;
}

.message-input {
    width: 100%;
    border: none;
    outline: none;
    background: transparent;
    font-size: 15px;
    padding: 8px 12px;
    color: #303030;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

.message-input::placeholder {
    color: #667781;
}

.send-button {
    min-width: 40px !important;
    width: 40px !important;
    height: 40px !important;
    background: #b0b3b8 !important;
    border-radius: 50% !important;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.send-button.has-text {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
    transform: scale(1);
}

.send-button:hover {
    transform: scale(1.05);
}

.send-button:active {
    transform: scale(0.95);
}

/* Emoji Picker */
.emoji-picker {
    max-width: 300px;
}

.emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 4px;
}

.emoji-btn {
    width: 32px;
    height: 32px;
    border: none;
    background: transparent;
    font-size: 20px;
    cursor: pointer;
    border-radius: 8px;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}

.emoji-btn:hover {
    background: #f0f2f5;
    transform: scale(1.2);
}

.emoji-btn:active {
    transform: scale(0.95);
}

/* Message Animations */
.message-fade-in {
    animation: fadeInUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.message-enter-active {
    animation: fadeInUp 0.3s ease-out;
}

.message-leave-active {
    animation: fadeInUp 0.2s ease-in reverse;
}

/* Mobile Optimizations */
@media (max-width: 600px) {
    .chatbot-container {
        border-radius: 10 !important;
    }

    .user-message {
        max-width: 80%;
    }

    .emoji-grid {
        grid-template-columns: repeat(6, 1fr);
    }
}

/* Prevent text selection on buttons */
.v-btn {
    user-select: none;
    -webkit-user-select: none;
}

/* Focus states */
.message-input:focus {
    outline: none;
}

/* Smooth scrolling */
.message-container {
    scroll-behavior: smooth;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a Secure QR Scanner with Geofencing in Vue.js</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Mon, 04 Aug 2025 06:50:32 +0000</pubDate>
      <link>https://forem.com/navnit73/building-a-secure-qr-scanner-with-geofencing-in-vuejs-32em</link>
      <guid>https://forem.com/navnit73/building-a-secure-qr-scanner-with-geofencing-in-vuejs-32em</guid>
      <description>&lt;p&gt;In today's mobile-first world, QR code scanning has become an essential feature for many applications, particularly in healthcare settings. In this post, I'll walk through how I built a secure QR scanner component for a hospital staff application that includes geofencing capabilities to ensure scanning only occurs within authorized locations.&lt;/p&gt;

&lt;p&gt;The Challenge&lt;br&gt;
The requirements for this scanner were specific:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only work when staff are physically within the hospital premises&lt;/li&gt;
&lt;li&gt;Provide both automatic QR scanning and manual UHID entry&lt;/li&gt;
&lt;li&gt;Include flash capability for low-light conditions&lt;/li&gt;
&lt;li&gt;Validate scanned data against backend systems&lt;/li&gt;
&lt;li&gt;Maintain security throughout the process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solution Architecture&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The component uses several key technologies:&lt;/li&gt;
&lt;li&gt;Vue 3 with Composition API for reactive UI&lt;/li&gt;
&lt;li&gt;qr-scanner library for efficient QR code detection&lt;/li&gt;
&lt;li&gt;Google Geolocation API for accurate positioning&lt;/li&gt;
&lt;li&gt;Vuetify for Material Design UI components&lt;/li&gt;
&lt;li&gt;Pinia for state management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1. Geofencing Implementation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async checkGeofence() {
  this.isLocating = true;
  this.locationError = 'Checking your location, please wait...';

  let userCoords = await this.getAccurateLocation();

  // Fallback to browser geolocation if Google API fails
  if (!userCoords &amp;amp;&amp;amp; navigator.geolocation) {
    userCoords = await this.getBrowserLocation();
  }

  if (!userCoords) {
    this.handleLocationError();
    return;
  }

  const distance = this.calculateDistance(this.hospitalLocation, userCoords);

  if (distance &amp;lt;= this.allowedRadius) {
    this.enableScanner();
  } else {
    this.disableScanner(distance);
  }

  this.isLocating = false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The geofencing uses the Haversine formula to calculate distance between coordinates:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getDistance(coords1, coords2) {
  const R = 6371e3; // Earth radius in meters
  const φ1 = (coords1.lat * Math.PI) / 180;
  const φ2 = (coords2.lat * Math.PI) / 180;
  const Δφ = ((coords2.lat - coords1.lat) * Math.PI) / 180;
  const Δλ = ((coords2.lon - coords1.lon) * Math.PI) / 180;

  const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + 
            Math.cos(φ1) * Math.cos(φ2) * 
            Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return R * c;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. QR Scanner Implementation&lt;br&gt;
The scanner initializes with optimal settings for healthcare use:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initScanner() {
  this.scannerRef = new QrScanner(
    this.$refs.videoRef,
    (result) =&amp;gt; {
      const decodedData = this.decodeBase64(result.data);
      if (decodedData) {
        this.processScanResult(decodedData);
      }
    },
    {
      highlightScanRegion: true,
      preferredCamera: 'environment',
      maxScansPerSecond: 1,
      returnDetailedScanResult: true
    }
  );

  this.scannerRef.start().catch(this.handleCameraError);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Manual Entry Fallback&lt;br&gt;
For cases where QR scanning isn't possible, we provide a manual entry option:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;v-fade-transition&amp;gt;
  &amp;lt;div v-if="showManualEntry" class="w-100 mt-2 d-flex align-center"&amp;gt;
    &amp;lt;v-text-field
      v-model="manualUhid"
      label="Enter UHID"
      variant="outlined"
      class="w-100"
      rounded="xl"
      density="compact"
      hide-details
    /&amp;gt;
    &amp;lt;v-btn
      @click="submitManualUhid"
      color="green"
      size="small"
      icon="mdi-check"
      class="ml-3"
      rounded="xl"
      elevation="2"
    /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/v-fade-transition&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Location Verification: Ensures scanning only occurs within hospital premises&lt;/li&gt;
&lt;li&gt;Base64 Decoding: Safely decodes and parses QR content&lt;/li&gt;
&lt;li&gt;Camera Permissions: Handles permission errors gracefully&lt;/li&gt;
&lt;li&gt;Data Validation: All scanned data is validated against backend systems
**
Challenges and Solutions**
&lt;strong&gt;Challenge: **Accurate location detection on mobile devices
**Solution:&lt;/strong&gt; Implemented a hybrid approach using Google's Geolocation API with browser geolocation fallback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Challenge:&lt;/strong&gt; Camera performance on low-end devices&lt;br&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Limited scan rate to 1 scan/second and optimized video settings&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge:&lt;/strong&gt; User experience in varying light conditions&lt;br&gt;
&lt;strong&gt;Solution:&lt;/strong&gt; Added flash toggle and clear visual feedback&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete code---&amp;gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div v-if="locationError" class="pa-4 text-center"&amp;gt;
            &amp;lt;v-alert type="error" variant="tonal" border="start" prominent&amp;gt;
                {{ locationError }}
            &amp;lt;/v-alert&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div v-if="isWithinRange"&amp;gt;
            &amp;lt;div class="scanner-wrapper"&amp;gt;
                &amp;lt;video
                    ref="videoRef"
                    class="scanner-video rounded-xl elevation-3"
                    :style="{ border: scanActive ? '2px solid #4CAF50' : '2px solid #757575' }"
                &amp;gt;&amp;lt;/video&amp;gt;
                &amp;lt;div class="scanner-frame"&amp;gt;
                    &amp;lt;div class="scan-line" :class="{ 'scan-animation': scanActive }"&amp;gt;&amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div class="d-flex flex-column align-center pa-4 gap-4"&amp;gt;
                &amp;lt;div class="d-flex justify-center align-center"&amp;gt;
                    &amp;lt;v-btn
                        @click="toggleManualEntry"
                        :color="showManualEntry ? 'green' : 'secondary'"
                        rounded="xl"
                        elevation="2"
                        :text="showManualEntry ? 'Close Manual Entry' : 'Enter UHID Manually'"
                    /&amp;gt;
                    &amp;lt;v-btn
                        v-if="cameraAvailable"
                        @click="toggleFlash"
                        :color="flashOn ? 'yellow' : 'grey-lighten-1'"
                        :icon="flashOn ? 'mdi-flashlight-off' : 'mdi-flashlight'"
                        class="ml-3"
                        size="small"
                        rounded="xl"
                        elevation="2"
                    /&amp;gt;
                    &amp;lt;v-btn
                        color="primary"
                        @click="checkGeofence"
                        rounded="xl"
                        class="ml-2"
                        elevation="2"
                        prepend-icon="mdi-crosshairs-gps"
                        text=" Current Location"
                    /&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;v-fade-transition&amp;gt;
                    &amp;lt;div v-if="showManualEntry" class="w-100 mt-2 d-flex align-center"&amp;gt;
                        &amp;lt;v-text-field
                            v-model="manualUhid"
                            label="Enter UHID"
                            variant="outlined"
                            class="w-100"
                            rounded="xl"
                            density="compact"
                            hide-details
                        /&amp;gt;
                        &amp;lt;v-btn
                            @click="submitManualUhid"
                            color="green"
                            size="small"
                            icon="mdi-check"
                            class="ml-3"
                            rounded="xl"
                            elevation="2"
                        /&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/v-fade-transition&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
import QrScanner from 'qr-scanner';
import { useStaffStore } from '@/store/staffStore.js';
import axios from 'axios';

export default {
    name: 'OBQRScanner',
    data() {
        return {
            scanActive: true,
            flashOn: false,
            scanResult: false,
            cameraAvailable: false,
            scannerRef: null,
            showManualEntry: false,
            manualUhid: null,
            hco_id: null,
            user_id: null,
            uhid: null,
            location_id: null,
            isLocating: false,
            visit_id: null,
            key: null,
            appointment_id: null,
            isWithinRange: false,
            locationError: 'Checking your location, please wait...',
            hospitalLocation: {
                lat: 25.9278416,
                lon: 83.6141056
            },
            allowedRadius: 300
        };
    },
    mounted() {
        this.checkGeofence();
    },
    beforeUnmount() {
        this.stopScanner();
    },
    computed: {
        user_type: () =&amp;gt; useStaffStore().user_type || ''
    },
    methods: {
        async getAccurateLocation() {
            const GOOGLE_API_KEY = import.meta.env.VITE_GOOGLE_GEOLOCATION_API_KEY;

            try {
                const response = await axios.post(`https://www.googleapis.com/geolocation/v1/geolocate?key=${GOOGLE_API_KEY}`, {
                    considerIp: 'true'
                });
                if (response.data &amp;amp;&amp;amp; response.data.location) {
                    const userCoords = {
                        lat: response.data.location.lat,
                        lon: response.data.location.lng,
                        accuracy: response.data.accuracy
                    };

                    console.log(' Google API location:', userCoords);
                    return userCoords;
                } else {
                    throw new Error('Failed to get location from Google API.');
                }
            } catch (error) {
                console.error('Google Geolocation API error:', error);
                return null;
            }
        },

        async checkGeofence() {
            this.isLocating = true;
            this.locationError = 'Checking your location, please wait...';

            let userCoords = await this.getAccurateLocation();

            // fallback
            if (!userCoords &amp;amp;&amp;amp; navigator.geolocation) {
                try {
                    userCoords = await new Promise((resolve, reject) =&amp;gt; {
                        navigator.geolocation.getCurrentPosition(
                            (pos) =&amp;gt; resolve({ lat: pos.coords.latitude, lon: pos.coords.longitude }),
                            (err) =&amp;gt; reject(err),
                            { enableHighAccuracy: true, timeout: 10000 }
                        );
                    });
                } catch (e) {
                    this.locationError = 'Unable to determine your location.';
                    this.isLocating = false;
                    return;
                }
            }

            if (!userCoords) {
                this.locationError = 'Location detection failed.';
                this.isLocating = false;
                return;
            }

            const distance = this.getDistance(this.hospitalLocation, userCoords);

            if (distance &amp;lt;= this.allowedRadius) {
                this.isWithinRange = true;
                this.locationError = null;
                this.$nextTick(() =&amp;gt; {
                    this.initScanner();
                });
            } else {
                this.isWithinRange = false;
                this.locationError = `Scanner Disabled: You are approximately ${distance.toFixed(0)} meters away and need to be within ${
                    this.allowedRadius
                } meters of the hospital.`;
            }

            this.isLocating = false;
        },

        getDistance(coords1, coords2) {
            const R = 6371e3;
            const φ1 = (coords1.lat * Math.PI) / 180;
            const φ2 = (coords2.lat * Math.PI) / 180;
            const Δφ = ((coords2.lat - coords1.lat) * Math.PI) / 180;
            const Δλ = ((coords2.lon - coords1.lon) * Math.PI) / 180;

            const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
            const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

            return R * c;
        },

        initScanner() {
            const videoRef = this.$refs.videoRef;

            if (!videoRef) {
                console.error('Scanner init failed: Video element not found.');
                return;
            }

            this.scannerRef = new QrScanner(
                videoRef,
                (result) =&amp;gt; {
                    const decodedData = this.decodeBase64(result.data);
                    if (decodedData) {
                        this.parseDecodedData(decodedData);
                        this.validatePatient();
                        this.scanResult = true;
                        this.scanActive = false;
                        this.scannerRef.stop();
                    }
                },
                {
                    highlightScanRegion: true,
                    highlightCodeOutline: true,
                    preferredCamera: 'environment',
                    maxScansPerSecond: 1,
                    returnDetailedScanResult: true
                }
            );

            this.scannerRef
                .start()
                .then(() =&amp;gt; {
                    this.cameraAvailable = true;
                })
                .catch((err) =&amp;gt; {
                    console.error('Camera error:', err);

                    if (err === 'NotAllowedError') {
                        this.locationError = 'Camera access was denied. Please enable camera permissions in your browser settings.';
                    } else {
                        this.locationError = `Could not start camera. Error: ${err.name || err}`;
                    }
                });
        },

        stopScanner() {
            if (this.scannerRef) {
                this.scannerRef.stop();
                this.scannerRef.destroy();
                this.scannerRef = null;
            }
        },
        toggleManualEntry() {
            this.showManualEntry = !this.showManualEntry;
            if (!this.showManualEntry) {
                this.manualUhid = null;
            }
        },
        submitManualUhid() {
            if (this.manualUhid) {
                this.uhid = this.manualUhid;
                this.validatePatient();
            }
        },
        toggleFlash() {
            if (this.cameraAvailable) {
                this.scannerRef.toggleFlash().then(() =&amp;gt; {
                    this.flashOn = !this.flashOn;
                });
            }
        },
        decodeBase64(base64Data) {
            try {
                const decoded = atob(base64Data);
                return JSON.parse(decoded);
            } catch (error) {
                console.error('Failed to decode base64 or parse JSON:', error);
                return null;
            }
        },
        parseDecodedData(decodedData) {
            this.hco_id = decodedData.hco_id;
            this.user_id = decodedData.user_id;
            this.uhid = decodedData.uhid;
            this.location_id = decodedData.location_id;
            this.visit_id = decodedData.visit_id;
            this.key = decodedData.key;
            this.appointment_id = decodedData.appointment_id || null;
        },
        async validatePatient() {
            try {
                const data = {
                    hco_id: this.hco_id,
                    user_id: this.user_id,
                    uhid: this.uhid,
                    location_id: 1,
                    visit_id: this.visit_id,
                    key: this.key,
                    event: this.user_type,
                    manualUhid: this.manualUhid,
                    appointment_id: this.appointment_id
                };

                const response = await axios.post('/staff/QrScanner.html?action=scanQR', data);

                if (response.data) {
                    this.stopScanner();
                    this.$router.go(-1);
                }
            } catch (error) {
                console.error('Error validating patient:', error);
            }
        }
    }
};
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
.qr-scanner-container {
    max-width: 100%;
    padding: 16px;
    height: 100vh;
    display: flex;
    flex-direction: column;
}

.scanner-wrapper {
    position: relative;
    width: 100%;
    margin: 0 auto;
    max-width: 400px;
}

.scanner-video {
    width: 100%;
    height: 400px;
    display: block;
    transition: all 0.3s ease;
}

.scanner-frame {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.scan-line {
    position: absolute;
    top: 50%;

    left: 30%;
    width: 39%;
    height: 2px;
    background: rgba(76, 175, 80, 0.8);
    box-shadow: 0 0 10px rgba(76, 175, 80, 0.8);
    z-index: 1;
}

.scan-animation {
    animation: scan 2s infinite linear;
}

@keyframes scan {
    0% {
        top: 10%;
    }
    100% {
        top: 90%;
    }
}
&amp;lt;/style&amp;gt;

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

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Creating a Gauge Chart (Speedometer) in Vue.js Using Vue Speedometer Plugin</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Fri, 30 May 2025 05:23:41 +0000</pubDate>
      <link>https://forem.com/navnit73/creating-a-gauge-chart-speedometer-in-vuejs-using-vue-speedometer-plugin-39pc</link>
      <guid>https://forem.com/navnit73/creating-a-gauge-chart-speedometer-in-vuejs-using-vue-speedometer-plugin-39pc</guid>
      <description>&lt;h1&gt;
  
  
  ⚡ Vue Advanced Speedometer — A Professional Gauge Chart for Vue 3
&lt;/h1&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%2F5qmhswr79130f8884dio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qmhswr79130f8884dio.png" alt="Gauge Types" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vue-speedometer-gauge-chart.vercel.app/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;br&gt;
Dashboards, monitoring systems, IoT panels, and analytics apps often need &lt;strong&gt;visual indicators&lt;/strong&gt; like speedometers or gauge charts.&lt;/p&gt;

&lt;p&gt;But most Vue gauge libraries are either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not customizable enough&lt;/li&gt;
&lt;li&gt;Not TypeScript friendly&lt;/li&gt;
&lt;li&gt;Not performant&lt;/li&gt;
&lt;li&gt;Or visually outdated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;strong&gt;Vue Advanced Speedometer&lt;/strong&gt; — a &lt;strong&gt;modern, customizable, TypeScript-first gauge component for Vue 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It renders with &lt;strong&gt;SVG&lt;/strong&gt;, supports &lt;strong&gt;animations&lt;/strong&gt;, and is designed for &lt;strong&gt;real-world dashboards&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzxdvibhoma5qwx8i4zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzxdvibhoma5qwx8i4zk.png" alt="Gradient Arcs" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  🚀 Vue Advanced Speedometer
&lt;/h1&gt;

&lt;p&gt;A &lt;strong&gt;professional-grade gauge chart library for Vue 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;✔ Vue 3 native&lt;br&gt;
✔ TypeScript support&lt;br&gt;
✔ Highly customizable&lt;br&gt;
✔ Smooth animations&lt;br&gt;
✔ Production ready&lt;/p&gt;

&lt;p&gt;GitHub&lt;br&gt;
&lt;a href="https://github.com/Navnit73/vue-speedometer-gauge-chart" rel="noopener noreferrer"&gt;https://github.com/Navnit73/vue-speedometer-gauge-chart&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  📦 Installation
&lt;/h1&gt;

&lt;p&gt;Install using your preferred package manager.&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;vue-advanced-speedometer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ⚙ Global Registration
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.ts&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;createApp&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;vue&lt;/span&gt;&lt;span class="dl"&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;VueSpeedometer&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;vue-advanced-speedometer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-advanced-speedometer/dist/style.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&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;./App.vue&lt;/span&gt;&lt;span class="dl"&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;createApp&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;VueSpeedometer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;VueSpeedometer&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;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  📌 Basic Usage
&lt;/h1&gt;

&lt;p&gt;The simplest example requires only &lt;strong&gt;value&lt;/strong&gt; and &lt;strong&gt;max&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"65"&lt;/span&gt; &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instantly renders a responsive animated gauge.&lt;/p&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage&lt;/li&gt;
&lt;li&gt;Performance scores&lt;/li&gt;
&lt;li&gt;KPIs&lt;/li&gt;
&lt;li&gt;Health indicators&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhcpnw13vyh7yh3j77gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhcpnw13vyh7yh3j77gm.png" alt="Alerts &amp;amp; Thresholds" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🎨 Customization Example
&lt;/h1&gt;

&lt;p&gt;You can easily customize the theme, animation, and gauge type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"180"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"full"&lt;/span&gt;
  &lt;span class="na"&gt;theme=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
  &lt;span class="na"&gt;:animationDuration=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Options include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;semi gauge&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;full circle&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;quarter gauge&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧩 Custom Segments
&lt;/h1&gt;

&lt;p&gt;Define colored ranges to show safe / warning / danger zones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;segments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&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="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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;#22c55e&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="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&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;#eab308&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="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&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;#ef4444&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"95"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"180"&lt;/span&gt;
  &lt;span class="na"&gt;:segments=&lt;/span&gt;&lt;span class="s"&gt;"segments"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health metrics&lt;/li&gt;
&lt;li&gt;Server load&lt;/li&gt;
&lt;li&gt;Risk indicators&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🌈 Gradient Gauges
&lt;/h1&gt;

&lt;p&gt;You can also render &lt;strong&gt;smooth gradient arcs&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"180"&lt;/span&gt;
  &lt;span class="na"&gt;:gradient=&lt;/span&gt;&lt;span class="s"&gt;"['#00ff88', '#ffaa00', '#ff3300']"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🚨 Alert Thresholds
&lt;/h1&gt;

&lt;p&gt;Trigger visual alerts when values cross thresholds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alerts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&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;#f59e0b&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;140&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;#ef4444&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"180"&lt;/span&gt;
  &lt;span class="na"&gt;:alerts=&lt;/span&gt;&lt;span class="s"&gt;"alerts"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;system monitoring&lt;/li&gt;
&lt;li&gt;analytics dashboards&lt;/li&gt;
&lt;li&gt;medical monitoring&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🎯 Custom Center Slot
&lt;/h1&gt;

&lt;p&gt;You can fully customize the &lt;strong&gt;center display&lt;/strong&gt; using Vue slots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt; &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"85"&lt;/span&gt; &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#center=&lt;/span&gt;&lt;span class="s"&gt;"{ value, percentage }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&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;"custom-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;%&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/VueSpeedometer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  ✨ New in v2.0
&lt;/h1&gt;

&lt;p&gt;Version &lt;strong&gt;2.0&lt;/strong&gt; introduces several powerful new features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Needle Support
&lt;/h3&gt;

&lt;p&gt;Display multiple metrics in one gauge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;needles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&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;#3b82f6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AVG&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;140&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;#ef4444&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MAX&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt; &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;:needles=&lt;/span&gt;&lt;span class="s"&gt;"needles"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Logarithmic Scale
&lt;/h3&gt;

&lt;p&gt;Useful for &lt;strong&gt;wide-range data&lt;/strong&gt; like metrics from &lt;code&gt;1 → 10000&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt;
  &lt;span class="na"&gt;:min=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"10000"&lt;/span&gt;
  &lt;span class="na"&gt;:logarithmic=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Custom Tick Labels
&lt;/h3&gt;

&lt;p&gt;Format ticks as &lt;strong&gt;currency, RPM, percentages, etc.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"4500"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"10000"&lt;/span&gt;
  &lt;span class="na"&gt;:formatTick=&lt;/span&gt;&lt;span class="s"&gt;"(v) =&amp;gt; '$' + v"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Concentric Arcs
&lt;/h3&gt;

&lt;p&gt;Add additional metrics around the main gauge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&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;#3b82f6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;70&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;#22c55e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VueSpeedometer&lt;/span&gt;
  &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"75"&lt;/span&gt;
  &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;
  &lt;span class="na"&gt;:concentricArcs=&lt;/span&gt;&lt;span class="s"&gt;"arcs"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🎮 Events
&lt;/h1&gt;

&lt;p&gt;The component emits useful lifecycle events.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;@value-change
@segment-enter
@segment-leave
@animation-end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to trigger logic like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alerts&lt;/li&gt;
&lt;li&gt;analytics&lt;/li&gt;
&lt;li&gt;notifications&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🛠 Exposed Methods
&lt;/h1&gt;

&lt;p&gt;Control the gauge programmatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;animateTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;speedometer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;animateTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also export the gauge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;exportAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;exportAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🧠 Full TypeScript Support
&lt;/h1&gt;

&lt;p&gt;The library exports typed interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Segment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;NeedleConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for &lt;strong&gt;TypeScript-first Vue apps&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  📊 Ideal Use Cases
&lt;/h1&gt;

&lt;p&gt;Vue Advanced Speedometer works great for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analytics dashboards&lt;/li&gt;
&lt;li&gt;IoT monitoring panels&lt;/li&gt;
&lt;li&gt;Medical systems&lt;/li&gt;
&lt;li&gt;Finance dashboards&lt;/li&gt;
&lt;li&gt;Admin panels&lt;/li&gt;
&lt;li&gt;Real-time metrics&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🔗 Links
&lt;/h1&gt;

&lt;p&gt;GitHub&lt;br&gt;
&lt;a href="https://github.com/Navnit73/vue-speedometer-gauge-chart" rel="noopener noreferrer"&gt;https://github.com/Navnit73/vue-speedometer-gauge-chart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/vue-advanced-speedometer-pro" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/vue-advanced-speedometer-pro&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ❤️ Built for the Vue Community
&lt;/h1&gt;

&lt;p&gt;Vue Advanced Speedometer is &lt;strong&gt;MIT licensed&lt;/strong&gt; and open for contributions.&lt;/p&gt;

&lt;p&gt;If you like it:&lt;/p&gt;

&lt;p&gt;⭐ Star the repository&lt;br&gt;
🐛 Report issues&lt;br&gt;
🚀 Contribute improvements&lt;/p&gt;

&lt;p&gt;Let’s build better Vue dashboards together.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>College dunia interview questions</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Sat, 14 Sep 2024 06:32:25 +0000</pubDate>
      <link>https://forem.com/navnit73/college-dunia-interview-questions-211b</link>
      <guid>https://forem.com/navnit73/college-dunia-interview-questions-211b</guid>
      <description>&lt;p&gt;Q1. Given an array of n elements that contains elements from 0 to n-1, with any of these numbers appearing any number of times. Find these repeating numbers in O(n) and use only constant memory space.&lt;/p&gt;

&lt;p&gt;Note: The repeating element should be printed only once.&lt;/p&gt;

&lt;p&gt;Input: n=7, array[]={1, 2, 3, 6, 3, 6, 1&lt;/p&gt;

&lt;p&gt;Output: 1, 3, 6&lt;/p&gt;

&lt;p&gt;Explanation. The numbers 1.3 and 6 appear more than once in the array.&lt;/p&gt;

&lt;p&gt;Q2. Given an array of integers, return all the elements having positive and negative values of a number that exists in the array,&lt;/p&gt;

&lt;p&gt;Note: If no such pair exists, simply retum an empty array, also multiple pairs of the same number could exist and you need to put each of them in the array. Return the pairs in sorted order.&lt;/p&gt;

&lt;p&gt;Expected Time Complexity O(nlog(n))&lt;/p&gt;

&lt;p&gt;Expected Auxiliary Space, O(n)&lt;/p&gt;

&lt;p&gt;Input: arr[] = [1, -3, 2, 3, 6,-1,-3,31&lt;/p&gt;

&lt;p&gt;Output: 1-1. 1, -3, 3-3.3]&lt;/p&gt;

&lt;p&gt;Explanation: The array contains both 1 and -1, and 3 &amp;amp;-3 two times&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Advance pattern python webkul interview</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Fri, 06 Sep 2024 02:25:08 +0000</pubDate>
      <link>https://forem.com/navnit73/advance-pattern-python-webkul-interview-2p3o</link>
      <guid>https://forem.com/navnit73/advance-pattern-python-webkul-interview-2p3o</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# n=4                  *    
#                      * *
#              ****eeee*   *
#         *    ****    * *
#       * *    ****    *
#     *   *eeee****
#       * *
#         *


n=4

for i in range(n//2):
    for j in range(3*n+n//2+1):
        print(' ',end='')
    for j in range(i+1):
        print('*',end='')
    print()

for i in range(1):
    for j in range(n+n//2+1):
        print(' ',end='')
    for j in range(n):
        print('*',end='')
    for j in range(n):
        print('e',end='')
    print('*',end='')
    for j in range(n//2-1):
        print(' ',end='')
    print('*')

for i in range(n//2):
    for j in range(n//2-i):
        print(' ',end='')
    for j in range(i+1):
        print('*',end='')
    for j in range(n):
        print(' ',end='')
    for j in range(n):
        print('*',end='')
    for j in range(n):
        print(' ',end='')
    for j in range(n//2-i):
        print('*',end='')
    print()

for i in range(1):
    print('*',end='')
    for j in range(n//2-1):
        print(' ',end='')
    print('*',end='')
    for j in range(n):
        print('e',end='')
    for j in range(n):
        print('*',end='')
    print()

for i in range(n//2):
    for j in range(i+1):
        print(' ',end='')
    for j in range(n//2-i):
        print('*',end='')
    print()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Webkul pattern question advance pattern for interview with python</title>
      <dc:creator>Navnit Rai</dc:creator>
      <pubDate>Thu, 05 Sep 2024 17:29:37 +0000</pubDate>
      <link>https://forem.com/navnit73/webkul-pattern-question-advance-pattern-for-interview-with-python-4hp1</link>
      <guid>https://forem.com/navnit73/webkul-pattern-question-advance-pattern-for-interview-with-python-4hp1</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n=5
for i in range(n-2):
    for j in range(i+1):
        print("*",end='')
    print()
print("*"*(n-1),end='')
print(" "*(n+1),end='')
print("*")
print("*"*(2*n+2))
print("*"*(n-1),end='')
print(" "*(n+1),end='')
print("*")

for i in range(n):
    for j in range(n-i-2):
        print("*",end='')
    print()                                

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.photoresizer.co.in/" rel="noopener noreferrer"&gt;https://www.photoresizer.co.in/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.photoresizer.co.in/" rel="noopener noreferrer"&gt;This free online photo resizer helps candidates resize photos for SSC CGL, UPSC, IBPS, Banking, Railway and other government exams. for dev.to post&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

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

# n=3
# *
# **    *
# ********
# **    *
# *

# n=5

# *             
# **           
# ***         
# ****      *
# ************
# ****      *
# ***
# ***
# **
# *       

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# #webkul pattern program round 1 
# #pattern runs for odd number like min 3 , 5, 7 etc
# #here is ther pattern
# #for n==3
# *       *
# **     **
# ***@@@***
#    @@@
#    @@@
#    ***
#     *
# #for n==5 
# *             *
# **           **
# ***         ***
# ****       ****
# *****@@@@@*****
#      @@@@@
#      @@@@@
#      @@@@@
#      @@@@@
#      *****
#       ***
#        *
# #and so on for n==7.....
# #here is the program


n=5
for i in range(n+1):
    for j in range(i):
        print('*',end='')
    for j in range(n-i):
        print(' ',end='')
    for j in range(n):
        if(i==n):
            print('@',end='')
        else:
            print(' ',end='')
    for j in range(n-i):
        print(' ',end='')
    for j in range(i):
        print('*',end='')
    print()
for i in range(n-1):5
    for j in range(3*n):
        if(j&amp;lt;n or j&amp;gt;2*n-1):
            print(' ',end='')
        else:
            print('@',end='')
    print()
for i in range(n//2+1):
    for j in range(n):
        print(' ',end='')
    for j in range(i):
        print(' ',end='')
    for j in range(n-2*i):
        print('*',end='')
    for j in range(i):
        print(' ',end='')
    for j in range(n):
        print(' ',end='')
    print()

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Input : 3
# Output : 
#                             @
#                            @@@
#                           @@@@@
#                           *   *
#                          **@@@**
#                           *   *
# Input : 5
# Output : 
#                             @
#                            @@@
#                           @@@@@
#                          @@@@@@@
#                          *     *
#                         **     **
#                        ***@@@@@***
#                         **     **
#                          *     *


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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n=3
for i in range(n//2+2):
    for j in  range(n-i):
        print(" ",end='')
    for j in range(1+2*i):
        print('@',end='')
    print()
for i in range(1,n//2+1):
    if(i&amp;lt;n//2+1):
        for j in range(n//2-i+1):
            print(' ',end='')
        for j in range(i):
            print("*",end="")
        for j in range(n):
            print(" ",end='')
        for j in range(i):
            print("*",end="")
    print()
for i in range(1):
    for j in range(n+2*(n//2+1)):
        if(j&amp;lt;n//2+1 or j&amp;gt;n+n//2):
            print("*",end='')
        else:
            print('@',end='')
    print()
for i in range(n//2):
    for j in range(i+1):
        print(' ',end='')
    for j in range(n//2-i):
        print('*',end='')
    for j in range(n):
        print(' ',end='')
    for j in range(n//2-i):
        print('*',end='')
    print()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

# @       
# @@      @@@
# @@@*****@@@
# @@      @@@
# @       


# n=5

# @          
# @@         @@@@@
# @@@        @@@@@
# @@@@*******@@@@@
# @@@        @@@@@
# @@         @@@@@
# @     


n=5
for i in range(n-1):
    for j in range(i+1):
        print('@',end='')
    for j in range(n-2-i):
        print('_',end='')
    for j in range(n+2):
        if(i==n-2):
            print('*',end='')
        else:
            print('_',end='')
    for j in range(n):
        if(i&amp;gt;0):
            print('@',end='')
        else:
            print('_',end='')
    print()

for i in range(n//2+1):
    for j in range(n//2+1-i):
        print('@',end='')
    for j in range(i):
        print('_',end='')
    for j in range(n+3):
        print('_',end='')
    for j in range (n):
        if(i&amp;lt;n//2):
            print('@',end='')
        else:
            print(' ',end='')
    print()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# n=3
#     *
#   ***
#   @ @   
# ***@ @***
#  *     *


# n=5
#       *
#       ***
#      *****
#      @   @     
#      @   @     
#      @   @     
# *****@   @*****
#  ***       ***
#   *         *



n=5
for i in range(n//2+1):
    for j in range(n):
        print(' ',end='')
    for j in range(n//2-i):
        print(' ',end='')
    for j in range(1+2*i):
        print('*',end='')
    print()
for i in range(n-1):
    for j in range(3*n):
        if(j==n or j==2*n-1):
            print('@',end='')
        elif(i==n-2 and(j&amp;lt;n or j&amp;gt;2*n-1)):
            print('*',end='')
        else:
            print(' ',end='')
    print()
for i in range(n//2):
    for j in range(i+1):
        print(' ',end='')
    for j in range(n-2-2*i):
        print('*',end='')
    for j in range(i+1):
        print(' ',end='')
    for j in range(n):
        print(' ',end='')
    for j in range(i+1):
        print(' ',end='')
    for j in range(n-2-2*i):
        print('*',end='')
    print()



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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n= int(input("enter only odd number"))


for i in range(n//2+1):
    for j in range(n//2):
        print("-",end="")
    for j in range(i):
        print("1",end="")
    for j in range(n-2*i):
        print("@",end="")
    print()

for i in range(n):
    for j in range(n):
        if i==0 or j==n-1 or j==0:
            print("*",end="")
        else:
            print("-",end="")



    print()```



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

&lt;/div&gt;

</description>
    </item>
  </channel>
</rss>
