<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by shipra shankhwar on Medium]]></title>
        <description><![CDATA[Stories by shipra shankhwar on Medium]]></description>
        <link>https://medium.com/@shankhwarshipra2001?source=rss-f34a4af7bb81------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*70-CNffJy-iZFFyi</url>
            <title>Stories by shipra shankhwar on Medium</title>
            <link>https://medium.com/@shankhwarshipra2001?source=rss-f34a4af7bb81------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 26 May 2026 22:56:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shankhwarshipra2001/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Beyond Code: Skills That Can Land You a Job as a Developer]]></title>
            <link>https://medium.com/@shankhwarshipra2001/beyond-code-skills-that-can-land-you-a-job-as-a-developer-23cc5925674b?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/23cc5925674b</guid>
            <category><![CDATA[job-search]]></category>
            <category><![CDATA[soft-skills]]></category>
            <category><![CDATA[career-development]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[developer]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Mon, 06 Oct 2025 10:56:01 GMT</pubDate>
            <atom:updated>2025-10-06T10:56:01.072Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pIas0KZxGA33_FL4" /></figure><p>When people think of landing a software development job, the spotlight usually falls on coding. And yes, coding is the foundation — without it, we wouldn’t even be here. But here’s the real secret: <strong>coding alone won’t get you hired, and it certainly won’t help you thrive once you’re in.</strong></p><p>Let’s talk about the often-overlooked skills that make you stand out in interviews and workplaces, even if your code looks just like the next applicant’s.</p><h3>1. Communication: Explaining Tech Without Jargon</h3><p>It’s one thing to write a function, and another to explain what that function does to a product manager who’s never written a line of code.</p><ul><li>In interviews, being able to clearly explain your approach to a problem is often valued more than brute-force coding speed.</li><li>At work, you’ll be explaining bugs, features, and ideas to people who don’t think in semicolons.</li></ul><p>👉 <strong>Pro tip:</strong> Practice explaining your latest project to a non-tech friend. If they understand it, you’ve nailed it.</p><h3>2. Problem-Solving Mindset: Code Is Just the Tool</h3><p>Think of coding as the hammer. The real skill is knowing what to build with it. Employers look for developers who:</p><ul><li>Can break down messy, vague problems into smaller, solvable pieces.</li><li>Don’t panic when the first solution doesn’t work.</li><li>See the bigger picture, not just the “for loop” in front of them.</li></ul><p>👉 Example: Instead of just writing an algorithm to “sort data,” think about <em>why</em> the data needs sorting and <em>how</em> the end-user will benefit. That’s problem-solving.</p><h3>3. Teamwork: Because No One Builds Alone</h3><p>You could be the fastest coder in the room, but if you don’t know how to work with others, progress will stall.</p><ul><li>Most real-world projects are team efforts — designers, testers, product managers, and other developers.</li><li>Good teamwork means listening, respecting deadlines, and sometimes even adjusting your style to fit the team.</li></ul><p>👉 Remember: “collaboration over competition” gets projects shipped faster.</p><h3>4. Adaptability: Tech Changes Overnight</h3><p>Frameworks, libraries, and languages evolve faster than you can finish that online course.</p><ul><li>Employers want people who can learn and adapt quickly.</li><li>It’s less about knowing every tool and more about showing you <em>can</em> learn new ones when the time comes.</li></ul><p>👉 Example: You don’t need to know every detail of Kubernetes to get hired. But if you show you can pick it up, that’s gold.</p><h3>5. Time Management &amp; Prioritization</h3><p>Being a developer isn’t about writing the most lines of code — it’s about writing the <em>right</em> lines of code at the <em>right</em> time.</p><ul><li>Can you prioritize urgent tasks?</li><li>Do you know when to stop perfecting and just ship?</li><li>Can you balance deep focus with quick team check-ins?</li></ul><p>👉 Those who manage time well are often trusted with bigger responsibilities sooner.</p><h3>6. Curiosity &amp; Continuous Learning</h3><p>This one’s underrated but powerful. Companies love developers who are curious and self-driven:</p><ul><li>Exploring side projects shows initiative.</li><li>Asking “why” instead of just “how” makes you valuable in shaping product decisions.</li><li>Staying updated on trends keeps your team future-ready.</li></ul><p>👉 A curious dev isn’t just an employee; they’re a growth engine.</p><h3>Final Thoughts</h3><p>Yes, you need to code well to be a developer. But here’s the truth: <strong>the best jobs and the best growth go to developers who mix coding with strong human and problem-solving skills.</strong></p><p>So next time you’re brushing up on your technical prep, take a moment to practice explaining concepts, working in teams, and staying adaptable. These are the skills that set you apart when ten candidates have written the same working solution.</p><p>Because in the end, companies aren’t just hiring code. They’re hiring people who can turn code into impact.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=23cc5925674b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Next.js Server Actions Explained: Real-World Examples for Developers]]></title>
            <link>https://medium.com/@shankhwarshipra2001/next-js-server-actions-explained-real-world-examples-for-developers-96881c8bdd2c?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/96881c8bdd2c</guid>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Fri, 03 Oct 2025 11:14:51 GMT</pubDate>
            <atom:updated>2025-10-03T11:14:51.395Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PJ5bldG86yqdXVrt" /></figure><p>Hey there! 👋</p><p>If you’ve been working with Next.js, you probably know how often we end up juggling <strong>API routes, fetch calls, and server logic</strong> just to do something simple like submit a form or talk to a database. Well, say hello to <strong>Server Actions</strong> — a neat way to run server-side code <strong>directly from your components</strong>.</p><p>In this article, I’ll break it down for you and give you <strong>real-world examples you can start using today</strong>. No fluff, just practical stuff. Let’s dive in.</p><h3>What Are Server Actions?</h3><p>Think of Server Actions as <strong>functions that live on the server but can be called from your client-side components</strong>.</p><p>Traditionally, you’d have to:</p><ol><li>Create an API route in pages/api.</li><li>Write a fetch() call from your component to hit that API.</li><li>Handle responses and errors.</li></ol><p>With Server Actions, <strong>you skip the API route</strong>. You just call a server function like a normal function, and Next.js handles the rest.</p><h3>Why This is Awesome</h3><ul><li><strong>Simpler code</strong>: Fewer files, less boilerplate.</li><li><strong>Secure</strong>: Secrets like API keys or database credentials stay on the server.</li><li><strong>Faster dev</strong>: No need to manage separate endpoints for simple actions.</li></ul><h3>How Server Actions Work (Super Simple Example)</h3><p>Let’s start with a <strong>basic example</strong>: adding a user to a database.</p><pre>// app/actions.js<br>&quot;use server&quot;;  // This marks the function as a server action<br><br>export async function addUser(user) {<br>  // Pretend database call<br>  const result = await database.users.create({ data: user });<br>  return result;<br>}</pre><pre>// app/page.jsx<br>import { addUser } from &quot;./actions&quot;;<br><br>export default function Page() {<br>  const handleAddUser = async () =&gt; {<br>    const user = { name: &quot;Shipra&quot;, email: &quot;shipra@example.com&quot; };<br>    const result = await addUser(user); // runs on the server automatically<br>    console.log(&quot;User added:&quot;, result);<br>  };<br><br>  return &lt;button onClick={handleAddUser}&gt;Add User&lt;/button&gt;;<br>}</pre><p>See that? No fetch() required. Next.js handles <strong>the client-server communication automatically</strong>.</p><p>Think of it like this: the <strong>button on your page</strong> tells the server, “Hey, add this user!” The <strong>server does the work</strong> safely, then sends back the result. You don’t see the messy API calls or database secrets — Next.js handles it all behind the scenes. Simple, clean, and secure.</p><h3>Real-World Example #1: Form Submission</h3><p>Imagine you have a contact form:</p><pre>// app/actions.js<br>&quot;use server&quot;;<br><br>export async function submitContactForm(data) {<br>  // Imagine sending an email or saving to a DB<br>  await sendEmail({<br>    to: &quot;team@example.com&quot;,<br>    subject: &quot;New Contact Form Submission&quot;,<br>    body: `Message from ${data.name}: ${data.message}`,<br>  });<br>  return { success: true };<br>}</pre><pre>// app/page.jsx<br>import { submitContactForm } from &quot;./actions&quot;;<br><br>export default function ContactForm() {<br>  const handleSubmit = async (e) =&gt; {<br>    e.preventDefault();<br>    const data = { name: &quot;Shipra&quot;, message: &quot;Hello there!&quot; };<br>    const response = await submitContactForm(data);<br>    if (response.success) alert(&quot;Form submitted successfully!&quot;);<br>  };<br>  return (<br>    &lt;form onSubmit={handleSubmit}&gt;<br>      &lt;button type=&quot;submit&quot;&gt;Send Message&lt;/button&gt;<br>    &lt;/form&gt;<br>  );<br>}</pre><p>No extra API endpoints, no manual fetch(). Just click a button, and your <strong>server-side logic runs safely</strong>.</p><h3>Real-World Example #2: CRUD Operations</h3><p>Server Actions are perfect for <strong>database operations</strong>. Let’s say you want to <strong>delete a user</strong>:</p><pre>// app/actions.js<br>&quot;use server&quot;;<br><br>export async function deleteUser(userId) {<br>  return await database.users.delete({ where: { id: userId } });<br>}</pre><pre>// app/page.jsx<br>import { deleteUser } from &quot;./actions&quot;;<br><br>export default function UserList({ users }) {<br>  const handleDelete = async (id) =&gt; {<br>    await deleteUser(id);<br>    alert(`User ${id} deleted!`);<br>  };<br>  <br>  return (<br>    &lt;ul&gt;<br>      {users.map((user) =&gt; (<br>        &lt;li key={user.id}&gt;<br>          {user.name} &lt;button onClick={() =&gt; handleDelete(user.id)}&gt;Delete&lt;/button&gt;<br>        &lt;/li&gt;<br>      ))}<br>    &lt;/ul&gt;<br>  );<br>}</pre><p>Notice how <strong>the client code stays super clean</strong>, but all database logic runs securely on the server.</p><h4>How This Delete Example Works</h4><ol><li><strong>Server-side deletion</strong><br> In app/actions.js, the deleteUser function is marked with &quot;use server&quot;. This tells Next.js that this function runs <strong>only on the server</strong>, where it safely interacts with the database to delete a user by their ID.</li><li><strong>Calling it from the client</strong><br> In the UserList component, each user has a “Delete” button. When clicked, handleDelete calls deleteUser(id). Even though it looks like a normal function call, <strong>Next.js automatically sends it to the server</strong>.</li><li><strong>Getting feedback</strong><br> Once the server finishes deleting, the client gets the result. Here, we simply show an alert to let the user know the deletion happened.</li><li><strong>User experience</strong><br> The user clicks → the server deletes → the client reacts. No API routes, no exposing secrets, just clean and safe code.</li></ol><h3>Tips for Using Server Actions</h3><ol><li><strong>Mark them with </strong><strong>&quot;use server&quot;</strong> — this is what tells Next.js it should run on the server.</li><li><strong>Keep secrets safe</strong> — passwords, API keys, database URLs, etc., should always stay in server actions.</li><li><strong>Use async/await</strong> — most server actions involve asynchronous operations like DB queries or network requests.</li><li><strong>Handle errors gracefully</strong> — even though they run on the server, you still want to catch and display errors properly.</li></ol><h3>When to Use Server Actions</h3><ul><li>Form submissions</li><li>Database CRUD operations</li><li>Sending emails or notifications</li><li>Anything that involves <strong>server-side secrets</strong></li></ul><p>Basically, <strong>anywhere you used to create a mini API endpoint</strong>, server actions can replace it.</p><h3>Wrapping Up</h3><p>Server Actions are a <strong>game-changer for Next.js developers</strong>. They make your code cleaner, your secrets safer, and your development faster.</p><p>If you’ve been frustrated by constantly switching between components and API routes, Server Actions will feel like a breath of fresh air.</p><p>Next step? Go try them in a small form or database operation — you’ll get hooked quickly!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=96881c8bdd2c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[10 Underrated Flutter Widgets That Can Save You Hours of Development]]></title>
            <link>https://medium.com/@shankhwarshipra2001/10-underrated-flutter-widgets-that-can-save-you-hours-of-development-108d800f54cb?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/108d800f54cb</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[programming-tips]]></category>
            <category><![CDATA[mobile-development]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[ui-design]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Fri, 12 Sep 2025 11:41:11 GMT</pubDate>
            <atom:updated>2025-09-12T11:41:11.683Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hGNtK_0ijs4DnqBB" /></figure><p>When we start with Flutter, most of us stick to the classics: Container, Row, Column, and maybe ListView. But Flutter’s widget catalog is massive, and many powerful widgets often fly under the radar.</p><p>In this article, I’ll walk you through 10 underrated Flutter widgets that can seriously speed up your workflow, reduce boilerplate, and make your apps more polished. I’ll keep it friendly and practical, with small examples you can drop right into your code.</p><h3>1. FractionallySizedBox</h3><p>Ever struggled with responsive layouts where you want a widget to take, say, 70% of the width? This widget saves the day.</p><pre>FractionallySizedBox(<br>  widthFactor: 0.7,<br>  child: ElevatedButton(<br>    onPressed: () {},<br>    child: Text(&quot;70% Width Button&quot;),<br>  ),<br>)</pre><p>Instead of juggling MediaQuery and manual calculations, this widget does it cleanly.</p><h3>2. AspectRatio</h3><p>Perfect for keeping consistent proportions (great for videos, cards, or images).</p><pre>AspectRatio(<br>  aspectRatio: 16 / 9,<br>  child: Container(<br>    color: Colors.blue,<br>    child: Center(child: Text(&quot;16:9 Box&quot;)),<br>  ),<br>)</pre><p>No more guessing heights when you already know the width.</p><h3>3. ClipRRect</h3><p>Rounded corners made easy — without manually setting borderRadius everywhere.</p><pre>ClipRRect(<br>  borderRadius: BorderRadius.circular(20),<br>  child: Image.network(&quot;https://via.placeholder.com/150&quot;),<br>)</pre><p>It’s one of the simplest ways to polish your UI.</p><h3>4. LimitedBox</h3><p>Ever had a ListView child grow infinitely because no constraints were given? LimitedBox keeps things under control.</p><pre>ListView(<br>  children: [<br>    LimitedBox(<br>      maxHeight: 200,<br>      child: Container(color: Colors.red),<br>    ),<br>  ],<br>)</pre><p>Especially handy when mixing scrollable and non-scrollable widgets.</p><h3>5. Expanded + Spacer</h3><p>Yes, you know Expanded, but do you use Spacer? It’s a clean way to add flexible empty space.</p><pre>Row(<br>  children: [<br>    Text(&quot;Left&quot;),<br>    Spacer(),<br>    Text(&quot;Right&quot;),<br>  ],<br>)</pre><p>Cleaner than adding an Expanded(child: Container()).</p><h3>6. Wrap</h3><p>Tired of Row or Column overflowing with widgets? Wrap makes items automatically move to the next line.</p><pre>Wrap(<br>  spacing: 8,<br>  runSpacing: 4,<br>  children: List.generate(10, (i) =&gt; Chip(label: Text(&quot;Item $i&quot;))),<br>)</pre><p>Your UI will thank you when text or chips don’t fit.</p><h3>7. ReorderableListView</h3><p>Need drag-and-drop reordering? Flutter gives it to you out of the box.</p><pre>ReorderableListView(<br>  onReorder: (oldIndex, newIndex) {},<br>  children: List.generate(<br>    5,<br>    (i) =&gt; ListTile(<br>      key: ValueKey(i),<br>      title: Text(&quot;Item $i&quot;),<br>    ),<br>  ),<br>)</pre><p>Saves you from reinventing the wheel with custom drag logic.</p><h3>8. AnimatedSwitcher</h3><p>Want smooth transitions when swapping widgets? Try this.</p><pre>int _count = 0; <br><br>AnimatedSwitcher(<br>  duration: Duration(milliseconds: 300),<br>  child: Text(<br>    &#39;$_count&#39;,<br>    key: ValueKey(_count),<br>    style: TextStyle(fontSize: 30),<br>  ),<br>)</pre><p>Whenever _count changes, the widget fades beautifully.</p><h3>9. DraggableScrollableSheet</h3><p>Think of the bottom sheet that expands in Google Maps — that’s this widget.</p><pre>DraggableScrollableSheet(<br>  builder: (context, controller) {<br>    return Container(<br>      color: Colors.white,<br>      child: ListView.builder(<br>        controller: controller,<br>        itemCount: 30,<br>        itemBuilder: (_, i) =&gt; ListTile(title: Text(&quot;Item $i&quot;)),<br>      ),<br>    );<br>  },<br>)</pre><p>It adds a slick UX with minimal code.</p><h3>10. FittedBox</h3><p>Say goodbye to overflowing text or icons — this widget automatically scales them down.</p><pre>FittedBox(<br>  child: Text(<br>    &quot;This is a very very very long text&quot;,<br>    style: TextStyle(fontSize: 30),<br>  ),<br>)</pre><p>A lifesaver when designing for multiple screen sizes.</p><p>Flutter’s beauty lies in its widget ecosystem. Once you explore beyond the basics, you’ll find widgets that feel like secret weapons — making your UI more responsive, interactive, and elegant with less effort.</p><p>The next time you’re wrestling with layouts or animations, try reaching for one of these underrated gems. They might just save you hours of development.</p><p>👉 Over to you: Which of these widgets do you use most, and which one surprised you?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=108d800f54cb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What the Bhagavad Gita Taught Me About Thriving in Corporate Life]]></title>
            <link>https://medium.com/@shankhwarshipra2001/what-the-bhagavad-gita-taught-me-about-thriving-in-corporate-life-bf6ae036aa8d?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/bf6ae036aa8d</guid>
            <category><![CDATA[bhagwad-gita]]></category>
            <category><![CDATA[careers]]></category>
            <category><![CDATA[corporate-culture]]></category>
            <category><![CDATA[leadership]]></category>
            <category><![CDATA[work-life-balance]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Sat, 26 Jul 2025 16:57:12 GMT</pubDate>
            <atom:updated>2025-07-26T16:57:12.040Z</atom:updated>
            <content:encoded><![CDATA[<p><em>The Gita isn’t a management book. But it’s helped me stay sane, sharp, and steady at work.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*q7knLsPZSG2vvl0u" /></figure><p>The Bhagavad Gita wasn’t written for boardrooms. No KPIs, no org charts, no corporate speak. Yet, as someone who’s spent years navigating meetings, deadlines, and internal politics, I’ve found its lessons more useful than any productivity hack or leadership course.</p><p>Here’s what this 2,000-year-old text has taught me about handling modern work life.</p><h3>1. Do the Work, Drop the Outcome</h3><blockquote><em>“You have a right to perform your duty, but not to the fruits of your actions.” — Gita 2.47</em></blockquote><p>Corporate culture is outcome-obsessed — targets, bonuses, recognition. But the Gita teaches detachment: focus on the work itself, not what it might bring.</p><p>This mindset shift reduces stress and boosts consistency. When your motivation isn’t tied to results, you become more resilient and less reactive. Ironically, you often perform better too.</p><h3>2. Get Clarity in the Chaos</h3><p>At the start of the Gita, Arjuna is paralyzed by doubt — stuck between duty and emotion. Krishna doesn’t hand him easy answers. He reframes the whole situation.</p><p>That’s the move: zoom out. When the job feels overwhelming, don’t just push harder. Step back. Ask bigger questions. What’s my role here? What really matters?</p><p>Perspective beats panic.</p><h3>3. Balance Is a Skill, Not a Luxury</h3><blockquote><em>“Yoga is skill in action.” — Gita 2.50</em></blockquote><p>Work-life balance is nice. But the Gita talks about a deeper kind of balance — emotional steadiness, presence without attachment.</p><p>In corporate life, that looks like staying calm in conflict, being unfazed by praise or criticism, and knowing when to act versus when to pause. This isn’t passivity. It’s power under control.</p><h3>4. Follow Your Swadharma (True Role)</h3><blockquote><em>“It is better to fail in your own dharma than to succeed in the dharma of another.” — Gita 3.35</em></blockquote><p>You weren’t built to copy someone else’s career path.</p><p>The Gita says: know your nature and act from it. In work terms, that means aligning with roles and projects that fit your values, strengths, and energy — even if it’s not the fastest path to the top.</p><p>Authenticity scales better than imitation.</p><h3>5. Ego Is the Real Enemy</h3><p>The higher you rise, the easier it is to mistake your title for your identity.</p><p>The Gita warns against this. Ego blocks growth. It makes you defensive, blinds you to feedback, and isolates you from your team.</p><p>Humility isn’t just noble — it’s practical. It makes you a better learner, a better listener, and a better leader.</p><h3>Final Thought: Ancient Wisdom, Modern Edge</h3><p>The Gita doesn’t offer a career plan. It offers something deeper: a mindset. One that anchors you in clarity, steadiness, and purpose — no matter what’s happening around you.</p><p>In the world of corporate hustle, that’s not just spiritual advice. That’s strategic advantage.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bf6ae036aa8d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Handle Form Data Types in Large Projects: A Shared TypeScript Strategy]]></title>
            <link>https://medium.com/@shankhwarshipra2001/how-i-handle-form-data-types-in-large-projects-a-shared-typescript-strategy-9d81fda1942e?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/9d81fda1942e</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[react-hook-form]]></category>
            <category><![CDATA[front-end-development]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Tue, 01 Jul 2025 10:57:40 GMT</pubDate>
            <atom:updated>2025-07-01T10:57:40.758Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*MiUOShjDTis0AOwm" /></figure><p>When you’re working on a small app, handling form data in TypeScript feels simple. You create a quick interface or type, pass it to your form library like react-hook-form, and move on.</p><p>But things change once the project gets bigger.</p><p>In large projects, you don’t just have one form. You have 10, 20, even 30 forms — all with different fields, create/edit modes, multilingual labels, conditional inputs, and sometimes role-specific logic.</p><p>That’s where problems start:</p><ul><li>You begin duplicating the same fields across multiple files.</li><li>Types for similar forms drift apart over time.</li><li>Bugs creep in when one part of your app expects a slightly different structure.</li><li>Maintenance becomes painful — especially when teams grow.</li></ul><p>I’ve dealt with this firsthand, and I realized something:</p><blockquote><strong><em>Form field types are not just random interfaces — they’re core building blocks.</em></strong></blockquote><p>So instead of defining types locally in every form page, I use a shared strategy — a single TypeScript file that holds all my reusable form field types. I treat fields like full_name, address, or school_info as modular units. I compose them into complete forms based on need.</p><p>This simple shift has made my forms cleaner, my validation more consistent, and my life much easier.</p><h3>The Challenge: Forms Scale Quickly, So I Plan Ahead</h3><p>As someone who likes to keep code clean and future-ready, I knew early on that handling form data types casually wouldn’t work in a growing project.</p><p>When a project is small, you might define form types locally — right where they’re used:</p><pre>interface LoginForm {<br>  username: string;<br>  password: string;<br>}</pre><p>That works fine when you’re only dealing with a couple of forms. But in a large-scale application — especially one with multiple roles, dynamic fields, and multilingual flows — forms aren’t small or isolated anymore.</p><p>You start encountering forms with:</p><ul><li>20+ fields</li><li>Shared sections like address, school info, Aadhaar details</li><li>“Create” and “Edit” modes that use the same data shape</li><li>Role-specific visibility (state admin sees more fields than a district user)</li><li>Label localization in 3+ languages (but same data structure)</li></ul><p>I didn’t want to wait until it became a mess.<br> So I designed a strategy early on that keeps things:</p><ul><li><strong>Modular</strong></li><li><strong>Consistent</strong></li><li><strong>Reusable across forms and pages</strong></li></ul><p>That meant moving away from defining full form types inline, and instead focusing on <strong>field-level types</strong> that can be composed like building blocks.</p><p>By planning ahead this way, I avoided:</p><ul><li>Repeating types for similar forms</li><li>Losing track of which form used which version of a field</li><li>Writing multiple validation schemas for the same field group</li></ul><p>This way, I treat form types the same way we treat components — <strong>reusable, predictable, and easy to manage</strong>.</p><h3>My Strategy: Shared TypeScript Types for Forms</h3><p>Instead of defining types per-page or per-component, I create a <strong>central file for all form types</strong>. This may seem unconventional in some teams, but it has worked <em>brilliantly</em> in my case.</p><h4>Folder Structure</h4><pre>/types<br>  └── formFields.ts</pre><p>All my reusable form field types live in formFields.ts. I don’t break them out per-page — that creates friction and duplication.</p><h4>What Goes Inside formFields.ts</h4><p>Each form or section gets a clearly named type.</p><pre>// formFields.ts<br><br>export interface FullNameField {<br>  full_name: string;<br>}<br><br>export interface AadhaarInfo {<br>  aadhaar_last_four: string;<br>}<br><br>export interface SchoolDetails {<br>  school_name: string;<br>  udise_code: string;<br>  academic_year_start: string;<br>  academic_year_end: string;<br>}<br><br>export interface AddressInfo {<br>  address_line_1: string;<br>  address_line_2?: string;<br>  village_city: string;<br>  brc: string;<br>  crc?: string;<br>  pin_code: string;<br>}</pre><h4>Composing Types Together</h4><p>The real power comes when I <strong>compose multiple types</strong> for larger forms.</p><pre>export type SchoolForm = FullNameField &amp;<br>  AadhaarInfo &amp;<br>  SchoolDetails &amp;<br>  AddressInfo;</pre><p>This gives me:</p><ul><li>Strong typing across pages/components</li><li>Easy reuse (e.g., if two pages use AddressInfo)</li><li>Clean validation schemas (with tools like yup or zod)</li><li>Support for create/edit modes with partials if needed</li></ul><p>And use it like this in your form:</p><pre>// SchoolFormComponent.tsx<br><br>import { useForm } from &#39;react-hook-form&#39;;<br>import type { SchoolForm } from &#39;@/types/formFields&#39;;<br><br>const SchoolFormComponent = () =&gt; {<br>  const { register, handleSubmit } = useForm&lt;SchoolForm&gt;();\<br><br>  const onSubmit = (data: SchoolForm) =&gt; {<br>    console.log(&#39;Submitted Data:&#39;, data);<br>  }<br><br>  return (<br>    &lt;form onSubmit={handleSubmit(onSubmit)}&gt;<br>      {/* Full Name */}<br>      &lt;input {...register(&#39;full_name&#39;)} placeholder=&quot;Full Name&quot; /&gt;<br><br>      {/* Aadhaar Info */}<br>      &lt;input {...register(&#39;aadhaar_last_four&#39;)} placeholder=&quot;Aadhaar Last 4 Digits&quot; /&gt;<br><br>      {/* School Details */}<br>      &lt;input {...register(&#39;school_name&#39;)} placeholder=&quot;School Name&quot; /&gt;<br>      &lt;input {...register(&#39;udise_code&#39;)} placeholder=&quot;UDISE Code&quot; /&gt;<br>      &lt;input {...register(&#39;academic_year_start&#39;)} placeholder=&quot;Academic Year Start&quot; /&gt;<br>      &lt;input {...register(&#39;academic_year_end&#39;)} placeholder=&quot;Academic Year End&quot; /&gt;<br><br>      {/* Address Info */}<br>      &lt;input {...register(&#39;address_line_1&#39;)} placeholder=&quot;Address Line 1&quot; /&gt;<br>      &lt;input {...register(&#39;address_line_2&#39;)} placeholder=&quot;Address Line 2 (Optional)&quot; /&gt;<br>      &lt;input {...register(&#39;village_city&#39;)} placeholder=&quot;Village/City&quot; /&gt;<br>      &lt;input {...register(&#39;brc&#39;)} placeholder=&quot;BRC&quot; /&gt;<br>      &lt;input {...register(&#39;crc&#39;)} placeholder=&quot;CRC (Optional)&quot; /&gt;<br>      &lt;input {...register(&#39;pin_code&#39;)} placeholder=&quot;PIN Code&quot; /&gt;<br><br>      &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;<br>    &lt;/form&gt;<br>  );<br>};<br><br>export default SchoolFormComponent;</pre><p>Now in my project, I am also having language support!<br>so here is how I achieve that too with this type of form and folder structure.</p><h3>Support for Multilingual Forms</h3><p>In my projects, forms often support multiple languages — like English (/en), Hindi (/hi), and Gujarati (/gu). But here’s the important part:</p><blockquote><em>While the language changes, the </em><strong><em>form structure stays exactly the same</em></strong><em>.</em></blockquote><p>So instead of defining separate form types for each language (which would be unnecessary and hard to maintain), I use the <strong>same TypeScript types</strong> — like SchoolForm — across all language versions of the app.</p><h4>Only Labels Change, Not Data</h4><p>What actually changes is:</p><ul><li>Field <strong>labels</strong> (like “Full Name” or “School Name”.</li><li><strong>Placeholders</strong>, <strong>error messages</strong>, and <strong>section headings</strong></li></ul><p>These are all handled by internationalization libraries like next-intl or react-i18next.</p><p>For example:</p><pre>&lt;label&gt;{t(&#39;full_name&#39;)}&lt;/label&gt;<br>&lt;input {...register(&#39;full_name&#39;)} placeholder={t(&#39;enter_full_name&#39;)} /&gt;</pre><p>So whether the user is on /en/school, /hi/school, or /gu/school, the SchoolForm type remains unchanged:</p><pre>type SchoolForm = FullNameField &amp; AadhaarInfo &amp; SchoolDetails &amp; AddressInfo;</pre><p>This keeps the validation, API payloads, and logic <strong>identical</strong>, which simplifies testing and maintenance — you’re only switching the UI language, not the data shape.</p><h4>Edit vs Create Mode Handling</h4><p>Another thing I often need is support for both <strong>Create</strong> and <strong>Edit</strong> modes using the <strong>same form</strong>.</p><p>In Create mode:</p><ul><li>All fields are usually empty</li><li>Validation is strict (e.g., required fields)</li></ul><p>In Edit mode:</p><ul><li>Most fields are pre-filled with existing data</li><li>Some fields may be optional, or skipped</li></ul><p>Now, instead of writing a separate type like EditSchoolForm, I simply reuse the original type but make all fields optional using TypeScript’s built-in Partial&lt;&gt; utility:</p><pre>type PartialSchoolForm = Partial&lt;SchoolForm&gt;;</pre><p>This gives me a flexible type where every field is optional:</p><pre>// Example: Edit form with prefilled data<br>const { register } = useForm&lt;PartialSchoolForm&gt;({<br>  defaultValues: {<br>    full_name: &#39;Existing Name&#39;,<br>    udise_code: &#39;123456&#39;,<br>    // others may be left blank<br>  }<br>});</pre><p>This is especially useful when:</p><ul><li>You fetch existing data from the API</li><li>You want to let users skip certain fields while editing</li><li>You want to reuse the same UI form without rewriting logic</li></ul><p>And best of all — you don’t need to define or maintain separate types for edit and create flows.</p><p>If your forms feel overwhelming or hard to maintain, try consolidating your field types into one shared file. Compose them like Lego blocks.</p><p>It’s one of those small things that makes a huge difference once your project grows.</p><p>💬 <em>Let me know your form handling strategy in the comments. Have a different approach that works for your team? I’d love to hear it.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9d81fda1942e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Real-World Folder Structure for a Multi-Role, Multi-Language Government App in Next.js]]></title>
            <link>https://medium.com/@shankhwarshipra2001/my-real-world-folder-structure-for-a-multi-role-multi-language-government-app-in-next-js-e8a35a224bea?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/e8a35a224bea</guid>
            <category><![CDATA[role-based-access-control]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[multi-language-website]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Fri, 27 Jun 2025 05:00:15 GMT</pubDate>
            <atom:updated>2025-06-27T05:01:26.181Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yBqTNSXtbKAtN4-f" /></figure><blockquote><em>How I structured a scalable and maintainable codebase for a multilingual, role-based government web application using Next.js 14+ App Router.</em></blockquote><p>Building government-grade applications isn’t just about ticking boxes for functionality — it’s about <strong>security</strong>, <strong>access control</strong>, <strong>accessibility</strong>, and <strong>long-term maintainability</strong>. Recently, I worked on a multilingual government portal built with <strong>Next.js</strong> using the new <strong>App Router</strong>, and supporting multiple user <strong>roles</strong> (e.g., state admin, school admin, viewer, etc.).</p><p>One of the biggest architectural decisions we made early on was: <strong>How do we organize our folders and files</strong> to scale as the app grows in features, roles, and languages?</p><p>In this article, I’ll walk you through the folder structure we landed on, the reasons behind every major decision, and how this structure made our life easier while building, testing, and maintaining the app.</p><h3>Requirements at a Glance</h3><p>Before jumping into the code, let me break down the real-world requirements that shaped our folder structure:</p><ul><li><strong>Multi-role Access</strong>: Different dashboards, pages, and permissions based on user roles (e.g., viewer, state_admin, country_admin).</li><li><strong>Multilingual Support</strong>: URLs are prefixed with the language code (/en, /hi, etc.), and translations are loaded dynamically.</li><li><strong>Multiple Layout Variations</strong>: Landing page has a public layout, dashboard pages have a sidebar + header, forms have a simpler layout.</li><li><strong>Route Protection with Middleware</strong>: Permissions are enforced both in middleware and per-page logic.</li><li><strong>Reusability and Clarity</strong>: Code should be easy to understand and reuse — especially for components, hooks, and types.</li><li><strong>Ease of Testing and Onboarding</strong>: Developers should instantly understand where to put and find things.</li></ul><h3>Project Overview</h3><p>Let’s take a look at a <strong>simplified version</strong> of the final folder structure:</p><pre>app/<br>├── [lang]/<br>│   ├── layout.tsx<br>│   ├── page.tsx              ← Public landing page<br>│   ├── dashboard/<br>│   │   ├── layout.tsx        ← Dashboard layout (sidebar + header)<br>│   │   └── page.tsx<br>│   ├── user-management/<br>│   │   ├── page.tsx          ← User list<br>│   │   ├── create/<br>│   │   │   └── page.tsx      ← Create form<br>│   │   └── [id]/edit/<br>│   │       └── page.tsx      ← Edit form<br>│   └── ...<br>├── middleware.ts<br>├── components/<br>│   ├── layout/<br>│   ├── forms/<br>│   ├── ui/<br>│   └── ...<br>├── constants/<br>├── lib/<br>│   ├── auth/<br>│   ├── i18n/<br>│   └── api/<br>├── hooks/<br>├── types/<br>├── styles/<br>└── public/</pre><h3>What’s Happening Behind Each Section?</h3><p>here the explanation is …….</p><h4>1. Multilingual Routing with [lang]/</h4><p>We use [lang] as a dynamic segment to prefix all routes:</p><ul><li>/en/dashboard</li><li>/hi/user-management</li></ul><p>This allows:</p><ul><li>Clean URL-based language switching.</li><li>Language-specific content and layout logic.</li><li>Easy middleware handling (e.g., redirecting / → /en by default).</li></ul><p><strong>Example:</strong></p><pre>// middleware.ts<br>const langRegex = /^\/(en|hi)(\/|$)/;<br>// validate user session &amp; redirect accordingly</pre><h4>2. Page-Level Layout Inheritance</h4><p>Next.js App Router allows layout composition by nesting.</p><pre>app/<br>└── [lang]/<br>    ├── layout.tsx         ← wraps all child routes<br>    └── dashboard/<br>        └── layout.tsx     ← wraps just dashboard and its subroutes</pre><p>This gives us:</p><ul><li><strong>Public Layout</strong> for landing/login.</li><li><strong>Dashboard Layout</strong> for sidebar + header.</li><li><strong>Form Layout</strong> (optional) for clean create/edit pages.</li></ul><h4>3. Role-Based Page Access</h4><p>We use <strong>middleware</strong> to block access based on roles and page type.</p><pre>// middleware.ts<br>if (pathname.includes(&#39;/dashboard&#39;) &amp;&amp; !user.roles.includes(&#39;admin&#39;)) {<br>  return NextResponse.redirect(new URL(`/${lang}/403`, request.url));<br>}</pre><p>Inside pages, we can still perform <strong>fine-grained checks</strong>:</p><pre>if (user.role !== &#39;country_admin&#39;) {<br>  return &lt;UnauthorizedAccess /&gt;;<br>}</pre><p>This 2-level check ensures security <em>and</em> user feedback.</p><h4>4. Clear Component Separation</h4><p>We divided components into purpose-specific folders:</p><p>Folder Purpose layout/ Layouts like SidebarLayout, Header forms/ Composable field blocks, file inputs ui/ Low-level inputs, buttons, toggles modals/ Shared modal components</p><p>This makes it easy to reason about whether you’re dealing with <strong>structure</strong> (layout), <strong>business logic</strong> (forms), or <strong>UI widgets</strong> (buttons, inputs).</p><h4>5. Centralized Constants and Enums</h4><p>The constants/ folder holds:</p><ul><li>Role definitions</li><li>API route mappings</li><li>Language keys</li><li>Permissions</li></ul><p>Example:</p><pre>export const _ROLES = {<br>  VIEWER: &#39;viewer&#39;,<br>  STATE_ADMIN: &#39;state_admin&#39;,<br>  COUNTRY_ADMIN: &#39;country_admin&#39;,<br>};</pre><h4>6. types/ and lib/ for Business Logic</h4><p>We separate data modeling (types/) from utility logic (lib/).</p><ul><li>types/: Form field types, API response models.</li><li>lib/api/: API call wrappers (using Axios/fetch).</li><li>lib/auth/: Login/logout helpers.</li><li>lib/i18n/: Dynamic translation loader and language switcher.</li></ul><p>This makes it very easy to:</p><ul><li>Reuse types across frontend/backend</li><li>Mock APIs during testing</li><li>Swap logic without touching UI code</li></ul><h4>7. Reusable Hooks</h4><p>All custom hooks go inside hooks/. Examples:</p><ul><li>useUserRole()</li><li>useLanguageSwitcher()</li><li>useFormSubmit()</li><li>useDebouncedSearch()</li></ul><p>Hooks isolate logic and keep components clean.</p><h3>Real Example: Create/Edit Page Flow</h3><p>Let’s say we want to build /en/user-management/create and /en/user-management/[id]/edit.</p><p>Here’s how we did it:</p><ul><li>Created shared form logic inside components/forms/UserForm.tsx</li><li>Loaded the page in:</li><li>app/[lang]/user-management/create/page.tsx</li><li>app/[lang]/user-management/[id]/edit/page.tsx</li><li>Used generateMetadata() for dynamic titles</li><li>Passed mode = &#39;create&#39; | &#39;edit&#39; as props to the form</li></ul><p>This avoids duplicating code and ensures consistency.</p><h3>Why This Structure Works in Production</h3><ul><li><strong>Discoverability</strong>: New devs immediately understand the layout.</li><li><strong>Testing &amp; Reus</strong>e: Easy to test logic (in hooks/lib) separately.</li><li><strong>Scalability</strong>: Easily add new roles, pages, or languages.</li><li><strong>Security</strong>: Enforced role access at middleware and component level.</li><li><strong>Separation of Concerns</strong>: Components, types, routes, logic — all live where they belong.</li></ul><p>Building a production-grade Next.js app for a multilingual, multi-role government portal is <strong>more than routing and styling</strong>. It’s about building a <strong>scalable foundation</strong> that supports your team and future development.</p><p>The folder structure I shared here is based on real challenges — not just theoretical best practices. Whether you’re building a school portal, admin dashboard, or citizen-facing app, this structure will help you stay organized and confident.</p><p>If you’re starting a complex Next.js project — especially one that involves roles and languages — consider starting with this architecture. It’s served us well in real-world use cases, and it’ll serve you too.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8a35a224bea" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Your React App Feels Sluggish]]></title>
            <link>https://medium.com/@shankhwarshipra2001/why-your-react-app-feels-sluggish-0b30ce160b8f?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/0b30ce160b8f</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[frontend]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Fri, 20 Jun 2025 06:31:56 GMT</pubDate>
            <atom:updated>2025-06-20T06:31:56.063Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0PSHWB6vSKXXYfVI" /></figure><p>React is fast. But your app? Not so much.</p><p>It’s frustrating — you follow best practices, split your components, maybe even use memoization. Still, performance feels off. Sluggish buttons. Delayed renders. Janky transitions.</p><p>The truth is: <strong>React’s slowness is rarely React’s fault.</strong> It’s usually yours. Or rather, it’s what you’re <em>ignoring</em>.</p><p>Let’s look at <strong>5 real reasons your app feels slow</strong>, and what you can do right now to fix them.</p><h3>1. 💥 Unbatched State Updates in Event Handlers</h3><p>React batches state updates inside synthetic events and lifecycle methods. But outside of those (e.g., inside setTimeout, fetch, or Promise.then()), it doesn’t batch by default — which leads to <strong>extra re-renders</strong>.</p><h3>The mistake:</h3><pre>setLoading(true);<br>setData(response.data); // Triggers two renders</pre><h3>The fix (React 18+):</h3><p>Use startTransition() or flushSync() when necessary:</p><pre>import { flushSync } from &#39;react-dom&#39;;<br><br>flushSync(() =&gt; {<br>  setLoading(true);<br>});<br>setData(response.data);</pre><p>Or combine state:</p><pre>setState({ loading: true, data: response.data });</pre><p><strong>Tip:</strong> Prefer batching logic or using reducers for grouped updates.</p><h3>2. 🎢 Useless Re-renders from Unmemoized Components</h3><p>Even small components re-rendering unnecessarily can bog down your UI — especially in lists, modals, or dashboards.</p><h3>The mistake:</h3><pre>const Item = ({ data }) =&gt; {<br>  console.log(&#39;Rendered&#39;); // Will log way too often<br>  return &lt;div&gt;{data.label}&lt;/div&gt;;<br>};</pre><h3>The fix:</h3><pre>const Item = React.memo(({ data }) =&gt; {<br>  return &lt;div&gt;{data.label}&lt;/div&gt;;<br>});</pre><p>Also use useCallback and useMemo to prevent prop changes that trigger children to re-render.</p><pre>const handleClick = useCallback(() =&gt; {<br>  doSomething();<br>}, []);</pre><h3>3. 🧠 Not Using Lazy Loading &amp; Code Splitting</h3><p>Why load the entire app when the user hasn’t even clicked beyond the login screen?</p><h3>The mistake:</h3><pre>import Dashboard from &#39;./Dashboard&#39;;</pre><h3>The fix:</h3><pre>const Dashboard = React.lazy(() =&gt; import(&#39;./Dashboard&#39;));</pre><p>Wrap with Suspense:</p><pre>&lt;Suspense fallback={&lt;Spinner /&gt;}&gt;<br>  &lt;Dashboard /&gt;<br>&lt;/Suspense&gt;</pre><p>Also consider tools like:</p><ul><li>React Router’s lazy routing</li><li>Vite or Webpack dynamic imports</li><li>Bundle Analyzer to spot large chunks</li></ul><h3>4. 📊 Not Virtualizing Large Lists</h3><p>Rendering 1,000+ DOM nodes is a quick way to kill performance — even if React is fast. Browsers still need to lay them all out.</p><h3>The fix: Virtualization</h3><p>Use tools like:</p><ul><li>react-window</li><li>react-virtualized</li></ul><p>Example:</p><pre>import { FixedSizeList as List } from &#39;react-window&#39;;<br><br>&lt;List<br>  height={400}<br>  itemCount={1000}<br>  itemSize={35}<br>  width={300}<br>&gt;<br>  {({ index, style }) =&gt; &lt;div style={style}&gt;Row {index}&lt;/div&gt;}<br>&lt;/List&gt;</pre><p>Only visible rows are rendered. Huge boost. 🔥</p><h3>5. ⚠️ Ignoring the DevTools Profiler</h3><p>If you’re guessing why your app is slow — stop. React ships with a <strong>Profiler tool</strong> that tells you exactly:</p><ul><li>Which components render too often</li><li>How long renders take</li><li>What props or states changed</li></ul><h3>How to use it:</h3><ol><li>Install React DevTools</li><li>Switch to the <strong>Profiler</strong> tab</li><li>Record interactions</li><li>Optimize based on real data</li></ol><p>You’ll be shocked how many “small” components render 50+ times unnecessarily.</p><h3>Final Thoughts</h3><p>Speed isn’t just about reducing file size — it’s about reducing <em>work</em>. Work React has to do. Work the browser has to do.</p><p>So next time your React app feels sluggish:</p><ul><li>Batch your state updates</li><li>Memoize what matters</li><li>Split your code smartly</li><li>Virtualize lists</li><li>Profile with purpose</li></ul><p>React gives you the tools. It’s up to you to use them right.</p><p><strong>Let your app feel as fast as it truly is. 🚀</strong></p><blockquote><strong><em>Enjoyed the article? Give it a 👏 or two!</em></strong></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0b30ce160b8f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Scalable Dashboard in Next.js with Role-Based Access and Language Support]]></title>
            <link>https://medium.com/@shankhwarshipra2001/building-a-scalable-dashboard-in-next-js-with-role-based-access-and-language-support-755f5bccb9dd?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/755f5bccb9dd</guid>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Thu, 19 Jun 2025 17:47:03 GMT</pubDate>
            <atom:updated>2025-06-19T17:47:03.772Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jRO2eEK5ZuRzpgbJ" /></figure><p>Let’s be real — most dashboards start off as a simple list and a couple of buttons. Maybe a login screen, a few forms, and you’re like, “Cool, it’s working!” But then someone says,<br> “Hey, can we hide this page for viewers?”<br> “Oh, we also need it in Hindi.”<br> “And there’s a new form coming… with a <em>slightly</em> different layout.”</p><p>Now you’re drowning in if-else conditions, duplicated components, and hardcoded text you’re praying never needs translation.</p><p>I’ve been there. That’s exactly why I decided to <strong>rebuild my dashboard architecture from the ground up</strong> — using <strong>Next.js</strong>, with a focus on <strong>role-based access</strong>, <strong>clean layouts</strong>, and <strong>language support that just works</strong>.</p><p>But this isn’t just another technical breakdown. Think of this like your future self looking back and thanking you for setting things up right the first time.</p><p>We’ll walk through:</p><ul><li>Creating separate layouts for different parts of your app — like landing pages, dashboards, and those annoying-but-necessary form pages.</li><li>Setting up <strong>middleware</strong> so that users only see what they’re allowed to see.</li><li>Adding language support in a way that makes your app ready for a global audience — without breaking your routing.</li></ul><p>It’s not about adding features. It’s about making your app <em>feel calm</em> — even when it’s doing a hundred things.</p><p>So grab your favorite beverage, open your code editor, and let’s start building a dashboard that’s as smart as it is scalable.</p><h3>Tech Stack</h3><ul><li><strong>Next.js (App Router)</strong></li><li><strong>React Hook Form</strong></li><li><strong>Zod (optional for validation)</strong></li><li><strong>i18next / next-i18next</strong></li><li><strong>TypeScript</strong></li></ul><p>One question that might be coming to your mind …..<br>“why this tech stack?”<br>Let me clear it for you.</p><p>When you’re building something that’s going to grow — especially a dashboard used by different roles and possibly in multiple languages — <strong>your tech choices matter</strong>. You don’t just want things that work; you want things that stay sane as features multiply. Here’s what I chose and <em>why it makes sense</em>:</p><h4>Next.js (App Router)</h4><p>Next.js gives you routing, layouts, and server-side rendering — all out of the box. But with the <strong>App Router</strong>, things get even cleaner. It supports <strong>nested layouts</strong>, <strong>server components</strong>, and <strong>dynamic routing</strong> in a way that just fits how real dashboards work.<br> Need a form with no sidebar? A page that only renders when localized? You can structure that beautifully without hacks.</p><h4>React Hook Form</h4><p>Forms are everywhere in a dashboard — login, user creation, settings, filters… you name it. react-hook-form makes form handling <em>fast</em>, <em>lightweight</em>, and <em>easy to scale</em>.<br> You get built-in support for controlled inputs, validation, and dynamic forms without re-render nightmares. Bonus: it plays well with TypeScript.</p><h4>Zod (optional, but smart)</h4><p>Zod is the TypeScript-loving validation library I reach for when I want <strong>schema-based form validation</strong>. While react-hook-form does basic checks, Zod lets you define a shape once and reuse it for both client-side forms and backend validation.<br> Think of it as your form’s bodyguard — strict, efficient, and reusable.</p><h4>i18next / next-i18next</h4><p>Supporting multiple languages shouldn’t be a painful add-on. next-i18next plugs into Next.js and gives you <strong>URL-based language routing</strong>, <strong>namespaced translations</strong>, and support for things like plurals and interpolation.<br> And i18n isn’t just about translation — it&#39;s about accessibility, reach, and user trust. If your app might go public (or serve government users), this is essential.</p><h4>TypeScript</h4><p>If you’re building something complex (like dashboards with multiple roles, routes, forms, and validations), <strong>TypeScript isn’t optional — it’s your safety net</strong>.<br> It catches bugs early, helps your IDE guide you while coding, and makes it easier to refactor confidently when your app inevitably grows.</p><h4>Middleware (for Role-Based Access Control)</h4><p>This is the hidden hero of the architecture. Next.js middleware lets you <strong>intercept requests before a page even loads</strong>. That means you can check the user’s role, block access to certain routes, and redirect them — all without rendering a thing.<br> It’s cleaner than adding logic on every page, and it keeps your access rules <strong>centralized and consistent</strong>.</p><p>Together, this stack isn’t just trendy — it’s built for <strong>clarity</strong>, <strong>scalability</strong>, and <strong>maintainability</strong>. Each tool solves a real problem that comes up in growing dashboards, and they all play nicely with each other.</p><h3>Laying the Foundation: Project Structure That Makes Sense</h3><p>Before we dive into components, routes, or forms, let’s get one thing straight — <strong>project structure is everything</strong>.</p><p>When you’re working with things like:</p><ul><li>A landing page for public visitors</li><li>A dashboard with a sidebar and private routes</li><li>Form pages that look and behave differently</li><li>Multilingual URLs (/en, /hi, etc.)</li><li>And user-based access control</li></ul><p>…you need to set up a <strong>folder structure that supports all of it — cleanly</strong>.</p><pre>app/<br>  [lang]/<br>    layout.tsx              → Global layout (based on language)<br>    page.tsx                → Landing Page (public)<br>    dashboard/<br>      layout.tsx            → Dashboard Layout (sidebar, header, etc.)<br>      page.tsx              → Dashboard Home<br>    user-management/<br>      page.tsx              → List view<br>      create/<br>        page.tsx            → Create User Form<br>      [id]/<br>        edit/<br>          page.tsx          → Edit User Form</pre><h4>Why this works:</h4><ul><li><strong>[lang]</strong> makes localization easy — the URL controls the language context (/en/dashboard, /hi/dashboard).</li><li><strong>Layouts</strong> are split: landing pages use a different layout than the dashboard or forms.</li><li><strong>Create/Edit pages</strong> have their own clean URLs — no query strings, easy to handle with access control.</li></ul><p>This setup keeps things modular, readable, and ready to scale. Whether you’re adding a new feature or applying role checks, you always know where your logic lives.</p><h3>🛡️ Role-Based Access Control with Middleware</h3><p>Now that our folder structure is ready, let’s talk about <strong>who gets to see what</strong>.</p><p>In a real-world dashboard, not every user should have access to every page. A school admin shouldn’t access super admin settings. A viewer might only be allowed to see certain sections, and not touch any forms at all. So how do we enforce that?</p><p>Instead of cluttering every page with permission checks, we do something smarter — we use <strong>middleware</strong>.</p><p>Middleware in Next.js lets you run logic <strong>before a request reaches the page</strong>. This is perfect for access control. It’s like a bouncer at the door — only letting the right people into the right rooms.</p><p>Here’s how I approached it.</p><h4>Understanding the Flow</h4><p>When a user navigates to a route — let’s say /en/user-management/create — the middleware runs <strong>before</strong> the page loads. At that point, we check:</p><ul><li>Is the user logged in?</li><li>Do they have the right role?</li><li>Are they allowed to access this path?</li></ul><p>If anything fails, we stop them right there — either by redirecting to the login page or showing a 403 Forbidden screen.</p><h4>The Role Logic</h4><p>I maintain role-based permissions in a centralized config — a simple object where each role is mapped to the routes it’s allowed to access.</p><p>When middleware runs, it grabs the current user’s role (usually from a token or session cookie), checks the requested path, and compares it with the allowed paths for that role. If it doesn’t match, access is denied.</p><p>No if-else blocks scattered across components. Just one central place to define what each role can and cannot do.</p><h4>Why Middleware Works Better</h4><p>If you’ve ever tried to handle access inside components, you know how messy it gets. Flashing pages, state-based checks, awkward redirects — it&#39;s not ideal.</p><p>Middleware avoids all that. It’s <strong>server-first</strong>, <strong>fast</strong>, and completely decouples access control from your UI code. It ensures that restricted pages don’t even begin to render for unauthorized users.</p><p>And because our routes are clean (/dashboard, /user-management, etc.), matching paths in middleware becomes straightforward.</p><p>This setup makes the app feel smoother and more secure. Users never see parts of the app they’re not supposed to, and developers aren’t stuck adding permission checks on every page.</p><h3>Language Support with next-i18next</h3><p>If you’re building an app in a multilingual country like India, supporting more than one language isn’t just a nice-to-have — it’s essential. You want your dashboard to feel personal, familiar, and accessible to users, whether they speak English, Hindi, or any other regional language.</p><p>But here’s the challenge: doing i18n right often ends up messy — scattered translation logic, inconsistent labels, weird bugs where only half the page gets translated.</p><p>That’s why I chose <strong>next-i18next</strong> — a powerful wrapper around the popular i18next library, made to work <em>seamlessly</em> with Next.js (especially the App Router).</p><p>Let me walk you through how I approached it.</p><h4>URL-Based Language Routing</h4><p>Instead of managing language with cookies or query parameters (which gets messy), I used <strong>language prefixes in the URL</strong> — like /en/dashboard or /hi/dashboard.</p><p>This way:</p><ul><li>Your language context is immediately clear.</li><li>Users can share links in their preferred language.</li><li>The router knows exactly what language to render at every level.</li></ul><p>All of this becomes super smooth with next-i18next. It automatically detects the language from the URL segment and loads the correct translation files without you writing manual logic.</p><h4>Translation File Structure</h4><p>Each namespace (like dashboard, form, common, etc.) has its own translation file — organized by language. For example:</p><pre>public/<br>  locales/<br>    en/<br>      common.json<br>      dashboard.json<br>    hi/<br>      common.json<br>      dashboard.json</pre><p>This lets you split translations logically and load only what’s needed on each page. So if you’re on the dashboard, it only loads the dashboard.json for that language.</p><p>Cleaner code, faster loads.</p><h4>In Components: Using useTranslation</h4><p>Once it’s all set up, using translations in your components is dead simple:</p><pre>const { t } = useTranslation(&#39;dashboard&#39;);<br>return &lt;h1&gt;{t(&#39;welcome_message&#39;)}&lt;/h1&gt;;</pre><p>But where does that welcome_message come from?<br>It lives in your translation files — one for each language. For example:</p><p>public/locales/en/dashboard.json</p><pre>{<br>  &quot;welcome_message&quot;: &quot;Welcome to your dashboard!&quot;<br>}</pre><p>public/locales/hi/dashboard.json</p><pre>{<br>  &quot;welcome_message&quot;: &quot;आपके डैशबोर्ड में आपका स्वागत है!&quot;<br>}</pre><p>With this setup, the app automatically picks the right message based on the current language in the URL (like /en/dashboard or /hi/dashboard). You don’t need to write any if (lang === &quot;en&quot;) logic anywhere — it just works.</p><h4>Bonus: Switching Languages</h4><p>If your header has a language selector, you can use router.push() to switch between /en/... and /hi/... — and the entire app updates instantly. The best part? You’re not manually reloading or juggling state. The URL handles it for you.</p><p>In short, next-i18next made the dashboard truly multilingual — in a way that’s <strong>clean</strong>, <strong>scalable</strong>, and most importantly, <strong>user-friendly</strong>.</p><h3>Component Reusability: Build Once, Use Everywhere</h3><p>When building dashboards, it’s tempting to just drop in inputs and buttons directly in each form or page. But once your app starts to grow, you’ll quickly realize: <strong>every extra field you duplicate is future technical debt</strong>.</p><p>That’s why I made every input, dropdown, and even date picker into a <strong>reusable component</strong>.</p><p>Here’s an example — let’s say we need a full name field in multiple forms (user form, school form, admin profile form, etc.). Instead of writing the same &lt;input /&gt; logic again and again, I created a reusable form field component using react-hook-form and TypeScript:</p><pre>// components/FormInput.tsx<br>&#39;use client&#39;;<br>import { Controller, Control } from &#39;react-hook-form&#39;;<br><br>type FormInputProps = {<br>  name: string;<br>  label: string;<br>  control: Control&lt;any&gt;;<br>  type?: string;<br>}<br><br>const FormInput = ({ name, label, control, type = &#39;text&#39; }: FormInputProps) =&gt; (<br>  &lt;div className=&quot;mb-4&quot;&gt;<br>    &lt;label className=&quot;block mb-1 font-medium text-gray-700&quot;&gt;{label}&lt;/label&gt;<br>    &lt;Controller<br>      name={name}<br>      control={control}<br>      render={({ field }) =&gt; (<br>        &lt;input<br>          {...field}<br>          type={type}<br>          className=&quot;w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500&quot;<br>        /&gt;<br>      )}<br>    /&gt;<br>  &lt;/div&gt;<br>);<br><br>export default FormInput;</pre><p>Now I can use it like this, anywhere:</p><pre>&lt;FormInput name=&quot;fullName&quot; label=&quot;Full Name&quot; control={control} /&gt;</pre><p>It looks consistent, behaves properly with form state, and is super easy to maintain. No need to repeat onChange, onBlur, or validation messages in every form.</p><p>This strategy works for all kinds of fields — selects, date pickers, file uploads, checkboxes. The more complex your form gets, the more valuable reusability becomes.</p><h3>UI Layout Strategy: Keeping Pages Clean, Contextual, and Smart</h3><p>Every part of your app doesn’t look the same — and it shouldn’t.</p><ul><li>Landing pages are clean and simple, with maybe a header and footer.</li><li>Dashboards have sidebars, headers, and user info.</li><li>Form pages often go full-width or remove distractions.</li></ul><p>To handle this elegantly, I use <strong>layout files</strong> in the App Router.</p><p>Here’s how it works:</p><h4>Folder Structure (again, briefly)</h4><pre>app/<br>  [lang]/<br>    layout.tsx              → Base layout (e.g., includes language, theme, etc.)<br>    page.tsx                → Landing page<br>    dashboard/<br>      layout.tsx            → Dashboard layout (sidebar, header)<br>      page.tsx              → Dashboard main view<br>    user-management/<br>      create/page.tsx       → Form page (minimal layout)</pre><h4>Base Layout: app/[lang]/layout.tsx</h4><p>This wraps all pages under a language, and is a good place for global wrappers like theming, font loading, or global providers.</p><pre>// app/[lang]/layout.tsx<br>import { ReactNode } from &#39;react&#39;;<br>import Header from &#39;@/components/Header&#39;;<br><br>export default function LangLayout({ children }: { children: ReactNode }) {<br>  return (<br>    &lt;html lang=&quot;en&quot;&gt;<br>      &lt;body className=&quot;bg-gray-50 text-gray-800&quot;&gt;<br>        &lt;Header /&gt;<br>        {children}<br>      &lt;/body&gt;<br>    &lt;/html&gt;<br>  );<br>}</pre><h4>Dashboard Layout: app/[lang]/dashboard/layout.tsx</h4><p>This layout wraps all pages inside the /dashboard route. It includes a sidebar on the left and a main content area on the right.</p><pre>// app/[lang]/dashboard/layout.tsx<br>import { ReactNode } from &#39;react&#39;;<br>import Sidebar from &#39;@/components/Sidebar&#39;;<br><br>export default function DashboardLayout({ children }: { children: ReactNode }) {<br>  return (<br>    &lt;div className=&quot;flex min-h-screen&quot;&gt;<br>      &lt;Sidebar /&gt;<br>      &lt;main className=&quot;flex-1 p-6 bg-white shadow-inner&quot;&gt;{children}&lt;/main&gt;<br>    &lt;/div&gt;<br>  );<br>}</pre><p>But what is &lt;Sidebar /&gt;? Let’s build it too — so when you run the app, it actually renders a usable UI.</p><h4>Sidebar Component: components/Sidebar.tsx</h4><p>This is a simple, clean sidebar with active link highlighting, built using next/navigation and clsx:</p><pre>&#39;use client&#39;;<br><br>import Link from &#39;next/link&#39;;<br>import { usePathname } from &#39;next/navigation&#39;;<br>import clsx from &#39;clsx&#39;;<br><br>const links = [<br>  { href: &#39;/en/dashboard&#39;, label: &#39;Dashboard&#39; },<br>  { href: &#39;/en/user-management&#39;, label: &#39;User Management&#39; },<br>  { href: &#39;/en/settings&#39;, label: &#39;Settings&#39; },<br>];<br><br>const Sidebar = () =&gt; {<br>  const pathname = usePathname();<br><br>  return (<br>    &lt;aside className=&quot;w-64 bg-gray-100 border-r min-h-screen p-4&quot;&gt;<br>      &lt;h2 className=&quot;text-xl font-semibold mb-6&quot;&gt;Admin Panel&lt;/h2&gt;<br>      &lt;nav className=&quot;flex flex-col gap-2&quot;&gt;<br>        {links.map((link) =&gt; (<br>          &lt;Link<br>            key={link.href}<br>            href={link.href}<br>            className={clsx(<br>              &#39;px-3 py-2 rounded hover:bg-blue-100 transition&#39;,<br>              pathname === link.href ? &#39;bg-blue-200 font-medium&#39; : &#39;text-gray-700&#39;<br>            )}<br>          &gt;<br>            {link.label}<br>          &lt;/Link&gt;<br>        ))}<br>      &lt;/nav&gt;<br>    &lt;/aside&gt;<br>  );<br>};<br><br>export default Sidebar;</pre><blockquote><em>🔧 </em><strong><em>Tip</em></strong><em>: If you’re not using path aliasing (</em><em>@/components/...), change the import to something like </em><em>../../../components/Sidebar.</em></blockquote><p>With this setup:</p><ul><li>The sidebar is consistent across all dashboard pages.</li><li>The active route is highlighted.</li><li>Navigation feels clean and modern.</li></ul><p>And best of all — it’s reusable. If you build another section like /school-management later, the layout stays the same — just plug in new pages under it.</p><h4>What This Renders</h4><p>When you visit /en/dashboard, this is what you&#39;ll <em>actually see</em> on the screen:</p><ul><li>The global header (from the root [lang]/layout.tsx)</li><li>The sidebar (from the /dashboard/layout.tsx)</li><li>The dashboard content (from /dashboard/page.tsx)</li></ul><p>And it’ll look clean, responsive, and separate from the layout you get on, say, the landing page or form screen.</p><h4>✍️ Minimal Layout for Forms</h4><p>Sometimes you want no sidebar — just a full-width clean form.</p><p>That’s easy: simply don’t define a layout in /user-management/create. It will fall back to the base [lang]/layout.tsx, which might just have the header.</p><p>Or, if you want to strip even that out — make your own layout.tsx under /user-management/ that renders only the form with a back button.</p><p>By breaking layouts up this way, you’re no longer wrapping every component in if (showSidebar) logic.</p><h3>Form Logic with React Hook Form + Zod</h3><p>If you’ve worked on dashboards for more than five minutes, you know one thing: <strong>forms are everywhere</strong>. Whether it’s adding a user, editing a school, applying filters, or submitting settings — forms are the main way users interact with your app.</p><p>And they can get messy fast. Different forms need different fields, some need validation, some are reused across multiple pages, and all of them need to behave reliably.</p><p>That’s why I chose <strong>React Hook Form</strong> for form state management — and paired it with <strong>Zod</strong> for schema-based validation. The result? Clean, efficient, and scalable forms that don’t need rewriting every time requirements change.</p><h4>Why React Hook Form?</h4><p>Unlike other form libraries that re-render on every keystroke, react-hook-form is performance-first. It’s also super easy to integrate with any kind of input — native, custom, or even 3rd-party components.</p><p>Even better: it works seamlessly with TypeScript, which means your forms are not just functional, they’re type-safe too.</p><h4>Adding Zod for Schema Validation</h4><p>While React Hook Form has built-in validation, I wanted more control — especially for complex validations, cross-field rules, and reusability. That’s where <strong>Zod</strong> comes in.</p><p>You define a schema once and use it for both form validation and backend validation if needed. It acts like a contract: the form must match this shape.</p><h4>A Real Example: Create/Edit User Form</h4><p>Let’s build a basic user form using react-hook-form, Zod, and the reusable input component we made earlier.</p><h4>Step 1: The Schema</h4><pre>// schemas/userSchema.ts<br>import { z } from &#39;zod&#39;;<br><br>export const userSchema = z.object({<br>  fullName: z.string().min(3, &#39;Full Name is required&#39;),<br>  email: z.string().email(&#39;Invalid email&#39;),<br>  role: z.enum([&#39;admin&#39;, &#39;viewer&#39;, &#39;editor&#39;], {<br>    errorMap: () =&gt; ({ message: &#39;Role is required&#39; })<br>  }),<br>});</pre><h4>🛠 Step 2: The Form Component</h4><pre>&#39;use client&#39;;<br><br>import { useForm } from &#39;react-hook-form&#39;;<br>import { zodResolver } from &#39;@hookform/resolvers/zod&#39;;<br>import { userSchema } from &#39;@/schemas/userSchema&#39;;<br>import FormInput from &#39;@/components/FormInput&#39;;<br>import { z } from &#39;zod&#39;;<br><br>type UserFormValues = z.infer&lt;typeof userSchema&gt;;<br><br>export default function UserForm() {<br>  const {<br>    handleSubmit,<br>    control,<br>    formState: { errors },<br>  } = useForm&lt;UserFormValues&gt;({<br>    resolver: zodResolver(userSchema),<br>    defaultValues: {<br>      fullName: &#39;&#39;,<br>      email: &#39;&#39;,<br>      role: &#39;viewer&#39;,<br>    },<br>  });<br><br>  const onSubmit = (data: UserFormValues) =&gt; {<br>    console.log(&#39;Submitted data:&#39;, data);<br>    // Send to API or dispatch to Redux, etc.<br>  };<br><br>  return (<br>    &lt;form onSubmit={handleSubmit(onSubmit)} className=&quot;max-w-md space-y-4&quot;&gt;<br>      &lt;FormInput name=&quot;fullName&quot; label=&quot;Full Name&quot; control={control} /&gt;<br>      &lt;FormInput name=&quot;email&quot; label=&quot;Email&quot; control={control} type=&quot;email&quot; /&gt;<br>      &lt;FormInput name=&quot;role&quot; label=&quot;Role&quot; control={control} /&gt;<br>      &lt;button<br>        type=&quot;submit&quot;<br>        className=&quot;px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700&quot;<br>      &gt;<br>        Submit<br>      &lt;/button&gt;<br>      {/* Simple error display (optional) */}<br>      {Object.values(errors).length &gt; 0 &amp;&amp; (<br>        &lt;div className=&quot;text-red-600 mt-2&quot;&gt;<br>          {Object.values(errors).map((err, idx) =&gt; (<br>            &lt;div key={idx}&gt;{err?.message}&lt;/div&gt;<br>          ))}<br>        &lt;/div&gt;<br>      )}<br>    &lt;/form&gt;<br>  );<br>}</pre><h4>Final Walkthrough: What We Built &amp; What It Delivers</h4><p>Let’s take a step back and see the bigger picture.</p><p>Over the course of this build, we’ve created more than just a dashboard — we designed a scalable foundation for a real-world admin interface.</p><p>Here’s what we now have:</p><ul><li>A <strong>clean project structure</strong> using Next.js App Router that separates landing pages, dashboard views, and form pages clearly — with language-aware routing built-in.</li><li><strong>Role-based access control</strong> using middleware, ensuring users only see what they’re allowed to, without extra logic inside every page.</li><li>Seamless <strong>language support</strong> with next-i18next, letting us show the entire UI in English, Hindi, or any future language — driven by URL segments and JSON files.</li><li>Fully <strong>reusable UI components</strong> (like inputs and dropdowns), making forms consistent, accessible, and easy to maintain.</li><li>Smart <strong>layout logic</strong> using nested layout.tsx files, where landing pages, dashboards, and forms all have their own clean layouts — without one bloated global wrapper.</li><li><strong>Form handling</strong> with react-hook-form and Zod, giving us instant validation, strong typing, and reliable submission logic.</li><li>A <strong>working Sidebar and form UI</strong>, so that when you run this locally and visit a route like /en/dashboard or /en/user-management/create, it <em>actually works</em> and looks good out of the box.</li></ul><h4>The Output?</h4><p>A modern dashboard that:</p><ul><li>Supports multiple user roles securely</li><li>Switches languages instantly</li><li>Has structured code ready for teams</li><li>Can scale with new modules and routes effortlessly</li></ul><p>No more clutter. No more hacks. Just a solid Next.js-based admin app that’s ready for production.</p><p>Feel free to take this, remix it, and scale it to fit your next project or team.</p><p>And if this helped you in any way — give it a share, a save, or just drop a comment.<br> Happy building! 🚀✨</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=755f5bccb9dd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Part 2: Mastering the Fundamentals — Templates, Loops, and Forms in Vue.js]]></title>
            <link>https://medium.com/@shankhwarshipra2001/part-2-mastering-the-fundamentals-templates-loops-and-forms-in-vue-js-4ff09a0fb9a9?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/4ff09a0fb9a9</guid>
            <category><![CDATA[vuejs]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[frontend]]></category>
            <category><![CDATA[beginners-guide]]></category>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Tue, 27 May 2025 10:24:51 GMT</pubDate>
            <atom:updated>2025-05-27T10:24:51.916Z</atom:updated>
            <content:encoded><![CDATA[<h3>Part 2: Mastering the Fundamentals — Templates, Loops, and Forms in Vue.js</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xVmRbX1qbEQCdQNI" /></figure><p>In <a href="https://medium.com/@shankhwarshipra2001/vue-js-from-beginner-to-expert-part-1-15ac15edad70">Part 1 of this series</a>, we laid the groundwork for your journey into the Vue.js ecosystem.</p><p>We didn’t just write “Hello World.” We walked through how to <strong>install Vue</strong>, <strong>understand its reactivity system</strong>, and see that magical moment when the UI updates automatically in response to your data changes.</p><p>We explored:</p><ul><li>What Vue is and why it’s gaining so much popularity</li><li>How it’s different from other frameworks like React or Angular</li><li>How to create your first Vue app with just a &lt;script&gt; tag or via Vite for more serious projects</li><li>The data() method and how it powers Vue&#39;s reactivity</li><li>Declaring methods inside the methods object and using them in the template</li><li>How to respond to user events using the @click directive</li></ul><p>By the end of Part 1, you hopefully understood how Vue connects your JavaScript logic to the browser’s DOM with minimal friction — and how it does so in a declarative, easy-to-follow way. We built a simple counter to demonstrate how user interactions could drive the application’s behavior. More importantly, we saw just how approachable Vue is, especially for developers coming from a vanilla JavaScript or jQuery background.</p><p>That first part was all about getting your hands dirty — to <strong>feel</strong> how Vue works.</p><p>But now it’s time to start building like a developer.</p><p>If you’ve made it this far, congratulations — you’re already ahead of most who just browse the docs and leave. You’ve taken action, written some code, and hopefully seen your first Vue app respond to your data in real time. That reactive feel — where the UI updates instantly with your logic — is what makes Vue such a pleasure to work with.</p><p>But right now, you’re likely at a crucial stage.</p><p>Maybe you’re asking:</p><ul><li>“How do I loop through items and render lists?”</li><li>“How do I show or hide elements dynamically?”</li><li>“How do I bind a class or style based on some logic?”</li><li>“How do I work with forms the Vue way?”</li><li>“How do I split up my app into smaller components?”</li></ul><p>These are all great questions — and that’s exactly what we’re covering in this part.</p><p>This article is all about mastering the <strong>core building blocks</strong> you’ll use daily when working with Vue. These aren’t advanced or obscure techniques — these are the tools that professional Vue developers use <strong>every single day</strong>.</p><p>We’ll take a hands-on approach, showing you practical examples of:</p><ul><li>Vue’s template syntax (v-bind, v-model, v-if, v-for)</li><li>How to style elements dynamically</li><li>Working with events and modifiers</li><li>Building forms with real-time two-way binding</li><li>Creating reusable components</li><li>Communicating between components via props and events</li></ul><p>This is where you start thinking in Vue — not just writing code that works, but understanding how and why things work in the Vue ecosystem.</p><p>Let’s dive in.</p><h3>1. Vue’s Template Syntax</h3><p>Vue uses special HTML attributes (called <strong>directives</strong>) that begin with v-. These connect your HTML to Vue’s data and logic.</p><h4>A) v-bind — Bind Attributes Dynamically</h4><pre>&lt;img v-bind:src=&quot;imageUrl&quot; /&gt;</pre><p>Shorthand:</p><pre>&lt;img :src=&quot;imageUrl&quot; /&gt;</pre><p>Use it to bind any HTML attribute: href, class, style, etc.</p><h4>Real-World Example</h4><pre>&lt;a :href=&quot;profileLink&quot; target=&quot;_blank&quot;&gt;Visit Profile&lt;/a&gt;<br><br>data() {<br>  return {<br>    profileLink: &#39;https://github.com/yourname&#39;<br>  };<br>}</pre><h4>B) v-if and v-else — Conditional Rendering</h4><pre>&lt;p v-if=&quot;isLoggedIn&quot;&gt;Welcome back!&lt;/p&gt;<br>&lt;p v-else&gt;Please log in.&lt;/p&gt;<br><br>data() {<br>  return {<br>    isLoggedIn: false<br>  };<br>}</pre><h4>C) v-for — Loop Through Data</h4><pre>&lt;ul&gt;<br>  &lt;li v-for=&quot;item in shoppingList&quot; :key=&quot;item.id&quot;&gt;<br>    {{ item.name }}<br>  &lt;/li&gt;<br>&lt;/ul&gt;<br><br>data() {<br>  return {<br>    shoppingList: [<br>      { id: 1, name: &#39;Milk&#39; },<br>      { id: 2, name: &#39;Bread&#39; },<br>      { id: 3, name: &#39;Eggs&#39; }<br>    ]<br>  };<br>}</pre><p>Remember: always include :key when looping to help Vue track changes efficiently.</p><h3>2. Binding Classes and Styles</h3><p>Vue allows dynamic styling directly in templates using :class and :style.</p><h4>A) Binding Classes Conditionally</h4><pre>&lt;p :class=&quot;{ active: isActive }&quot;&gt;Toggle me&lt;/p&gt;<br><br>data() {<br>  return { isActive: true };<br>}</pre><h4>B) Binding Inline Styles</h4><pre>&lt;p :style=&quot;{ color: textColor, fontSize: fontSize + &#39;px&#39; }&quot;&gt;Styled text&lt;/p&gt;<br><br>data() {<br>  return {<br>    textColor: &#39;red&#39;,<br>    fontSize: 18<br>  };<br>}</pre><h3>3. Event Modifiers</h3><p>Vue provides modifiers to control how events behave.</p><ul><li>.prevent: prevents the default behavior</li><li>.stop: stops the event from bubbling up</li><li>.once: the event is triggered only once</li></ul><h4>Example:</h4><pre>&lt;form @submit.prevent=&quot;handleSubmit&quot;&gt;...&lt;/form&gt;</pre><p>This prevents the page from reloading on form submission.</p><h3>4. Form Handling with v-model</h3><p>v-model provides two-way binding between inputs and your Vue data.</p><pre>&lt;input v-model=&quot;name&quot; placeholder=&quot;Enter your name&quot; /&gt;<br>&lt;p&gt;Hello, {{ name }}!&lt;/p&gt;<br><br>data() {<br>  return {<br>    name: &#39;&#39;<br>  };<br>}</pre><p>Works with input, textarea, select, checkboxes, and radios.</p><h3>5. Creating Reusable Components</h3><p>Vue components let you split your app into manageable, reusable parts.</p><h4>Example: Greeting.vue</h4><pre>&lt;template&gt;<br>  &lt;p&gt;Hello, {{ name }}!&lt;/p&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default {<br>  props: [&#39;name&#39;]<br>};<br>&lt;/script&gt;</pre><p>Use it like this:</p><pre>&lt;Greeting name=&quot;Alice&quot; /&gt;<br>&lt;Greeting name=&quot;Bob&quot; /&gt;</pre><h3>6. Emitting Events from Components</h3><p>Child components can communicate with parent components by emitting custom events.</p><h4>Child (Button.vue)</h4><pre>&lt;template&gt;<br>  &lt;button @click=&quot;$emit(&#39;say-hi&#39;)&quot;&gt;Say Hi&lt;/button&gt;<br>&lt;/template&gt;</pre><h4>Parent (App.vue)</h4><pre>&lt;Button @say-hi=&quot;handleHi&quot; /&gt;<br><br>methods: {<br>  handleHi() {<br>    alert(&#39;Hi from child!&#39;);<br>  }<br>}</pre><h3>Recap: What You’ve Learned</h3><ul><li>Use v-bind, v-if, v-for, v-model to build dynamic UIs</li><li>Dynamically bind styles and classes</li><li>Use event modifiers to control DOM behavior</li><li>Handle user input with reactive data</li><li>Create and reuse components with props</li><li>Send events from child to parent with $emit</li></ul><h3>What’s Next?</h3><p>In <strong>Part 3</strong>, we’ll cover:</p><ul><li>Vue CLI or Vite for real-world projects</li><li>Project structure and organization</li><li>Routing with Vue Router</li><li>State management with Pinia</li><li>Building a multi-page Vue application</li></ul><p>This was Part 2 of my “Vue.js from Beginner to Expert” series. You can find the link of first part in the beginning of this article or in my profile -&gt; stories.<br>After covering all these 4 parts, I will also publish a full front-end project using Vue.js.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4ff09a0fb9a9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[“Vue.js from Beginner to Expert”: Part 1]]></title>
            <link>https://medium.com/@shankhwarshipra2001/vue-js-from-beginner-to-expert-part-1-15ac15edad70?source=rss-f34a4af7bb81------2</link>
            <guid isPermaLink="false">https://medium.com/p/15ac15edad70</guid>
            <dc:creator><![CDATA[shipra shankhwar]]></dc:creator>
            <pubDate>Fri, 23 May 2025 15:10:51 GMT</pubDate>
            <atom:updated>2025-05-23T15:26:27.823Z</atom:updated>
            <content:encoded><![CDATA[<h3>“Vue.js from Beginner to Expert”</h3><h4>📚 Part 1: Getting Started with Vue.js — A Beginner’s Friendly Guide</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jeN3qDgeHENk7ggI" /></figure><h4>📚 Part 1: Getting Started with Vue.js — A Beginner’s Friendly Guide</h4><ul><li>What is Vue.js?</li><li>Why Vue (vs React/Angular)?</li><li>How Vue works (basic idea of reactivity)</li><li>How to add Vue via CDN</li><li>How to create your first Vue app</li><li>Vue instance, data(), and methods</li><li>Simple event handling and binding</li><li>First interactive app (like a counter or todo)</li></ul><h4>🔗 Part 2: Mastering the Fundamentals — Templates, Loops, and Forms in Vue.js</h4><ul><li>Template syntax (v-bind, v-model, v-if, v-for)</li><li>Binding styles and classes</li><li>Event modifiers</li><li>Form handling with v-model</li><li>Creating reusable components</li><li>Passing props and emitting events</li></ul><h4>🧠 Part 3: Going Modular — Vue CLI, Routing, and State Management</h4><ul><li>Installing via Vue CLI or Vite</li><li>File structure and components</li><li>Routing with Vue Router</li><li>Introduction to Pinia (state management)</li><li>Building a small multipage app</li></ul><h4>⚙️ Part 4: Advanced Vue Concepts — Composition API, Best Practices &amp; Real-World Patterns</h4><ul><li>Why and how to use Composition API</li><li>Refs vs reactive</li><li>watch, computed, and lifecycle hooks</li><li>Folder structure and code organization</li><li>Best practices and performance tips</li><li>What to learn next: VueUse, Nuxt, testing</li></ul><p>Now, let’s dive into the <strong>first article</strong>:</p><h3>📚 Part 1: Getting Started with Vue.js — A Beginner’s Friendly Guide</h3><p><strong>Are you completely new to Vue.js?</strong> You’ve come to the right place. In this guide, we won’t assume you know anything about JavaScript frameworks. We’ll explain what Vue is, why it’s beginner-friendly, and walk you through creating your very first interactive app — all with <strong>just a browser and a text editor</strong>.</p><h3>What is Vue.js?</h3><p>Vue.js (pronounced like “view”) is a JavaScript framework for building interactive web interfaces. It helps you build apps where the content changes dynamically without reloading the page — like counters, forms, dashboards, or even entire websites.</p><p>Think of it like this:<br> 👉 HTML builds your page<br> 👉 JavaScript adds interactivity<br> 👉 Vue helps you organize both and make them work together more easily</p><h3>🧠 Why Choose Vue (Especially as a Beginner)?</h3><ul><li>✅ <strong>Simple to start</strong>: You don’t need to install anything to try it out.</li><li>✅ <strong>Clean syntax</strong>: Looks like regular HTML with a little JavaScript.</li><li>✅ <strong>Fast results</strong>: Build something interactive in under 5 minutes.</li><li>✅ <strong>Scales well</strong>: You can go from small projects to big apps easily.</li></ul><h3>🚀 Let’s Create Your First Vue App (No Installation!)</h3><p>Create a new HTML file called index.html. Paste this into it:</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html&gt;<br>  &lt;head&gt;<br>    &lt;title&gt;Vue Hello World&lt;/title&gt;<br>    &lt;script src=&quot;https://unpkg.com/vue@3&quot;&gt;&lt;/script&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;div id=&quot;app&quot;&gt;<br>      &lt;h1&gt;{{ message }}&lt;/h1&gt;<br>      &lt;button @click=&quot;changeMessage&quot;&gt;Click Me&lt;/button&gt;<br>    &lt;/div&gt;<br><br>    &lt;script&gt;<br>      const { createApp } = Vue;<br><br>      createApp({<br>        data() {<br>          return {<br>            message: &#39;Hello from Vue!&#39;<br>          };<br>        },<br>        methods: {<br>          changeMessage() {<br>            this.message = &#39;You clicked the button!&#39;;<br>          }<br>        }<br>      }).mount(&#39;#app&#39;);<br>    &lt;/script&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><h3>🔍 What’s Happening Here?</h3><ul><li>{{ message }} — This is Vue’s way of displaying dynamic data.</li><li>@click=&quot;changeMessage&quot; — This listens for a click and runs a function.</li><li>The data() method returns reactive values.</li><li>The methods section contains your functions.</li></ul><h4>✨ Try Editing It Yourself</h4><ul><li>Change the text of message</li><li>Add a second button that changes the message to something else</li><li>Add a new piece of data, like a name, and display it</li></ul><h3>🛠️ Build Your First Small App: A Counter</h3><p>Here’s a basic counter app:</p><pre>&lt;div id=&quot;app&quot;&gt;<br>  &lt;h2&gt;Counter: {{ count }}&lt;/h2&gt;<br>  &lt;button @click=&quot;count++&quot;&gt;Increment&lt;/button&gt;<br>  &lt;button @click=&quot;count--&quot;&gt;Decrement&lt;/button&gt;<br>&lt;/div&gt;<br><br>&lt;script&gt;<br>  const { createApp } = Vue;<br><br>  createApp({<br>    data() {<br>      return {<br>        count: 0<br>      };<br>    }<br>  }).mount(&#39;#app&#39;);<br>&lt;/script&gt;</pre><p>No refresh needed — Vue handles all DOM updates for you.</p><h3>🧩 What You Learned So Far</h3><ul><li>How to include Vue in a webpage</li><li>What data() and methods are</li><li>How to make your page interactive</li><li>How Vue updates the UI reactively</li></ul><p>This is the foundation of Vue — and you’ve already created a dynamic app!</p><h3>👉 What’s Next?</h3><p>In <strong>Part 2</strong>, we’ll cover:</p><ul><li>Vue’s special attributes (v-bind, v-for, v-if, v-model)</li><li>Making forms and lists</li><li>Writing reusable components</li></ul><p>Stick with me — by the end of this series, you’ll be writing Vue apps with confidence!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=15ac15edad70" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>