<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nader Fkih Hassen</title>
    <description>The latest articles on DEV Community by Nader Fkih Hassen (@nader_fh).</description>
    <link>https://dev.to/nader_fh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3262148%2F745935c9-267d-4343-8031-e875fff118fa.png</url>
      <title>DEV Community: Nader Fkih Hassen</title>
      <link>https://dev.to/nader_fh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nader_fh"/>
    <language>en</language>
    <item>
      <title>Day 25 – Making Search and Filter Work Like Magic</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Fri, 11 Jul 2025 20:24:33 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-25-making-search-and-filter-work-like-magic-l84</link>
      <guid>https://dev.to/nader_fh/day-25-making-search-and-filter-work-like-magic-l84</guid>
      <description>&lt;p&gt;One of the most important things I’ve learned during my internship is that user experience is built in the details.&lt;/p&gt;

&lt;p&gt;Today’s challenge? Search and filtering for legal cases inside Lura.&lt;/p&gt;

&lt;p&gt;Lawyers work with hundreds of cases. Scrolling manually isn’t practical. They need fast, flexible ways to find what they’re looking for. Our job as developers is to create features that feel simple — even if they're not.&lt;/p&gt;

&lt;p&gt;🧠 Why It Matters&lt;br&gt;
In Lura, every case is tied to a workspace, and every document to a case. As the data grows, finding specific content becomes harder. Lawyers need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search by title (e.g., “Doe vs Smith”)&lt;/li&gt;
&lt;li&gt;Tag-based filtering (e.g., “Criminal”, “Pending”)&lt;/li&gt;
&lt;li&gt;Workspace-scoped results (can’t show data across teams)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this, the app feels clunky. With it, it becomes a tool that actually helps users think and act faster.&lt;/p&gt;

&lt;p&gt;⚙️ How I Built It&lt;br&gt;
📦 Backend: NestJS + Prisma&lt;br&gt;
I built a GET endpoint like &lt;code&gt;/cases?search=...&amp;amp;tag=...&amp;amp;workspace=...&lt;/code&gt;&lt;br&gt;
In the controller, I used Prisma to dynamically filter based on query params:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts
const cases = await prisma.case.findMany({
  where: {
    title: { contains: search },
    workspaceId,
    tags: { some: { name: tag } },
  },
  include: { tags: true }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made the filtering flexible and efficient. Prisma made chaining filters feel natural.&lt;/p&gt;

&lt;p&gt;💻 Frontend: Next.js + TailwindCSS&lt;br&gt;
I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A search bar with debounced input (to avoid spamming the backend)&lt;/li&gt;
&lt;li&gt;A tag selector dropdown&lt;/li&gt;
&lt;li&gt;A workspace switcher that resets filters when you move teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each interaction triggers a router query update, which then fetches the correct results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsx
router.push({
  pathname: '/cases',
  query: { search, tag, workspace }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I used &lt;code&gt;useEffect&lt;/code&gt; to trigger fetching on query change. Everything updates without a full reload — just like a proper SPA should.&lt;/p&gt;

&lt;p&gt;✨ The Result&lt;br&gt;
Users can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type to instantly filter by title&lt;/li&gt;
&lt;li&gt;Click tags to narrow down results&lt;/li&gt;
&lt;li&gt;Switch workspaces with isolated results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It feels fast. It feels modern. And more importantly: it helps the user get to work faster.&lt;/p&gt;

&lt;p&gt;✅ Takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filtering is UX power — it saves time and makes apps feel smarter.&lt;/li&gt;
&lt;li&gt;Prisma’s flexible querying makes dynamic filters easier than expected.&lt;/li&gt;
&lt;li&gt;State and URL sync in Next.js is a must-have for clean navigation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Question for You&lt;br&gt;
What’s your go-to strategy for building smart filtering systems?&lt;br&gt;
Do you prefer using server-side filters, or handle them on the client?&lt;/p&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>programming</category>
    </item>
    <item>
      <title>Day 24 – Experiencing Real Teamwork in Software Development</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Thu, 10 Jul 2025 15:48:12 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-24-experiencing-real-teamwork-in-software-development-f6e</link>
      <guid>https://dev.to/nader_fh/day-24-experiencing-real-teamwork-in-software-development-f6e</guid>
      <description>&lt;p&gt;During my time as a computer science student, we always worked on group projects — but let’s be honest: it’s usually just one or two people doing most of the work. Real teamwork? I thought I understood it.&lt;/p&gt;

&lt;p&gt;Then I started my internship and worked on Lura, our full-stack lawyer management system — and suddenly, I saw what it actually means to be part of a real software development team.&lt;/p&gt;

&lt;p&gt;💼 It’s Not About Just “Working Together”&lt;br&gt;
I used to think teamwork meant:&lt;/p&gt;

&lt;p&gt;“Just be nice and don’t step on toes.”&lt;/p&gt;

&lt;p&gt;But what I learned is that real teams communicate, disagree constructively, and plan constantly. We had proper daily standups, backlog grooming, sprint planning, and retrospectives. Not to mention reviewing PRs with real feedback — not just a 👍.&lt;/p&gt;

&lt;p&gt;🛠️ What I Did This Week&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Took part in resolving merge conflicts in GitHub (finally learned not to fear them 😅).&lt;/li&gt;
&lt;li&gt;Wrote detailed commit messages that actually made sense to others.&lt;/li&gt;
&lt;li&gt;Helped fix bugs introduced by features I didn't even write.&lt;/li&gt;
&lt;li&gt;Reviewed code, left comments, and asked clarifying questions when I didn’t understand something.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These might seem small, but it’s what teamwork really looks like — understanding the whole app, not just your part of it.&lt;/p&gt;

&lt;p&gt;🤯 Realizations That Changed the Way I Work&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Communication is Everything
The more I talked, the better we worked. Silent struggle helps no one.&lt;/li&gt;
&lt;li&gt;Accountability Matters
When a feature breaks, it’s not about blame — it’s about solving it together.&lt;/li&gt;
&lt;li&gt;No One Writes Perfect Code
Even the best devs need feedback and edits. The magic is in collaboration.&lt;/li&gt;
&lt;li&gt;Structure Helps, Not Hinders
I used to roll my eyes at GitHub issues and structured planning. But now? I can’t imagine working without them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👨‍💻 Takeaway&lt;br&gt;
Working in a real development team showed me how important process, patience, and people are. It’s not just about tech stacks — it’s about trust and timing. I’m grateful to my teammates and mentors who gave me the space to grow, ask questions, and even mess up (sometimes).&lt;/p&gt;

&lt;p&gt;I came into this internship wanting to become a better developer.&lt;br&gt;
  I’m leaving it with a better understanding of what it means to be teammate.&lt;/p&gt;

&lt;p&gt;❓Your Turn&lt;br&gt;
What was the biggest surprise for you when you started working with a dev team for the first time?&lt;br&gt;
Let me know — I’d love to learn from your experience too!&lt;/p&gt;

</description>
      <category>30daysoflearning</category>
      <category>scrum</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Day 23: My First Real Developer Experience</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Wed, 09 Jul 2025 15:07:22 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-23-my-first-real-developer-experience-1b0p</link>
      <guid>https://dev.to/nader_fh/day-23-my-first-real-developer-experience-1b0p</guid>
      <description>&lt;p&gt;I used to think that knowing how to code meant I was ready to work in a company. I had built some personal projects, passed some online courses, and contributed to group assignments at university.&lt;/p&gt;

&lt;p&gt;But after spending a few weeks at my internship with StartupFACTORY, I realized there’s a whole different level to being a real developer.&lt;/p&gt;

&lt;p&gt;👥 What Changed?&lt;br&gt;
It wasn’t the frameworks or tools. I already knew some JavaScript, had played with React, and learned NestJS during the early weeks of training.&lt;/p&gt;

&lt;p&gt;What changed was the environment.&lt;/p&gt;

&lt;p&gt;Suddenly, I was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing code that would be reviewed by someone else&lt;/li&gt;
&lt;li&gt;Explaining my decisions in a pull request&lt;/li&gt;
&lt;li&gt;Responding to constructive feedback&lt;/li&gt;
&lt;li&gt;Breaking something in one workspace and realizing it affected five others&lt;/li&gt;
&lt;li&gt;Writing TODOs not for myself, but for my teammates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This wasn’t a tutorial — this was a real product, being built for real users. That pressure changes everything.&lt;/p&gt;

&lt;p&gt;🛠️ Tools, But with Purpose&lt;br&gt;
Using GitHub felt different now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each branch had a ticket and a purpose&lt;/li&gt;
&lt;li&gt;Every commit message mattered&lt;/li&gt;
&lt;li&gt;Merge conflicts had real consequences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Scrum wasn’t just a school concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We had sprint goals&lt;/li&gt;
&lt;li&gt;We had reviews and retrospectives&lt;/li&gt;
&lt;li&gt;We adjusted based on blockers, not guesses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even writing a button component became an act of collaboration.&lt;/p&gt;

&lt;p&gt;💬 What I Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💡 Code that works isn’t always code that fits — consistency and readability matter.&lt;/li&gt;
&lt;li&gt;🤝 Asking for help is a strength, not a weakness. The team culture encourages open communication.&lt;/li&gt;
&lt;li&gt;🧭 Following structure (Scrum, planning, backlog) brings clarity — and reduces chaos.&lt;/li&gt;
&lt;li&gt;🧱 Real development is about sustainability, not just building fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔁 Reflection&lt;br&gt;
What was the first moment you felt like a “real” dev — not just someone writing code?&lt;/p&gt;

&lt;p&gt;For me, it was when my mentor asked, “Will this scale to multiple workspaces?” — and I didn’t have an answer. That one question changed the way I built everything after.&lt;/p&gt;

&lt;p&gt;Today wasn’t about learning a new library. It was about realizing how much I still have to learn to work like a professional. And that’s the most motivating feeling in the world.&lt;/p&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>devjournal</category>
      <category>programming</category>
    </item>
    <item>
      <title>Day 22: Building a Workspace-Centric Calendar System</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Tue, 08 Jul 2025 14:05:13 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-22-building-a-workspace-centric-calendar-system-3jl1</link>
      <guid>https://dev.to/nader_fh/day-22-building-a-workspace-centric-calendar-system-3jl1</guid>
      <description>&lt;p&gt;🗓️ Why Calendars Matter in a Lawyer Management System&lt;br&gt;
Lura, the app we’re building during my internship, is built around workspaces where legal professionals manage cases, documents, and more. One thing they all needed? A centralized, collaborative calendar.&lt;/p&gt;

&lt;p&gt;But it’s not just about putting dates on a page — it’s about communication, accountability, and structure.&lt;/p&gt;

&lt;p&gt;💡 Feature Goals for the Calendar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and edit case-related events (meetings, court dates, deadlines)&lt;/li&gt;
&lt;li&gt;Events should be linked to a workspace, not globally shared&lt;/li&gt;
&lt;li&gt;Only workspace members can view and manage their calendar&lt;/li&gt;
&lt;li&gt;Support recurring events (future enhancement)&lt;/li&gt;
&lt;li&gt;Simple, intuitive UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔧 Technical Breakdown&lt;br&gt;
📦 Backend (NestJS + Prisma)&lt;br&gt;
Created an &lt;code&gt;Event&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts
model Event {
  id          String   @id @default(uuid())
  title       String
  description String?
  date        DateTime
  workspaceId String
  createdBy   String
  createdAt   DateTime @default(now())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Added routes for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /events&lt;/code&gt;: Create a new event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /workspaces/&lt;/code&gt;:id/events: List events per workspace&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT /events/&lt;/code&gt;🆔 Edit event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /events/&lt;/code&gt;🆔 Delete event&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Used class-validator to handle input DTOs with proper date formatting.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;💻 Frontend (Next.js + FullCalendar)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrated FullCalendar to render a beautiful, interactive calendar.&lt;/li&gt;
&lt;li&gt;Used React hooks and context to handle user roles and event permissions.&lt;/li&gt;
&lt;li&gt;Built a modal form to add/edit events and hook into API routes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsx
const handleSubmit = async () =&amp;gt; {
  const res = await fetch('/api/events', {
    method: 'POST',
    body: JSON.stringify({ title, date }),
    headers: { 'Content-Type': 'application/json' },
  });
  const data = await res.json();
  mutate(); // refresh event list
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔐 Role-Based Access&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only workspace members can view/edit calendar events.&lt;/li&gt;
&lt;li&gt;Admins and Super Admins can delete any event.&lt;/li&gt;
&lt;li&gt;Used middleware on the backend to validate token and role on each action.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;📆 Calendars look simple but hide lots of edge cases (time zones, ownership, validation).&lt;/li&gt;
&lt;li&gt;👨‍💻 FullCalendar is a powerful library, but integrating with custom APIs takes care.&lt;/li&gt;
&lt;li&gt;🔐 Role-based logic really adds value to team collaboration features.&lt;/li&gt;
&lt;li&gt;🧠 Legal apps need precision and traceability — even in UI elements like calendars.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Question for You&lt;br&gt;
How do you usually handle shared calendar systems in your apps? Do you prefer an in-app solution or integrations like Google Calendar?&lt;/p&gt;

&lt;p&gt;Thanks for following along this journey — we’re nearing the finish line! 💪&lt;br&gt;
Stay tuned for Day 23.&lt;/p&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Day 21: Backend Security – The Last Line of Defense</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Mon, 07 Jul 2025 15:49:52 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-21-backend-security-the-last-line-of-defense-3p1k</link>
      <guid>https://dev.to/nader_fh/day-21-backend-security-the-last-line-of-defense-3p1k</guid>
      <description>&lt;p&gt;"Sometimes it’s not about what you add, but what you protect."&lt;/p&gt;

&lt;p&gt;In my internship journey, I revisited a crucial lesson that every developer (especially full-stack ones) should hold dear: never trust the frontend when it comes to security.&lt;/p&gt;

&lt;p&gt;🔍 The Problem&lt;br&gt;
In the early days of building Lura – The Lawyer Management System, we did most of our RBAC (Role-Based Access Control) checks on the frontend. Buttons were shown or hidden based on role, navigation was blocked, and unauthorized users couldn’t even see actions they shouldn’t take.&lt;/p&gt;

&lt;p&gt;It felt secure... until I asked myself:&lt;br&gt;
“What happens if someone just sends a crafted POST request directly to our backend?”&lt;/p&gt;

&lt;p&gt;Answer: They might just bypass all our hard work.&lt;/p&gt;

&lt;p&gt;🔒 The Solution: Backend Enforcement&lt;br&gt;
So I shifted focus and began securing our NestJS backend endpoints. Here's what I did:&lt;/p&gt;

&lt;p&gt;🧰 Backend Guards and Decorators&lt;br&gt;
I created a series of &lt;code&gt;custom guards&lt;/code&gt; and &lt;code&gt;decorators&lt;/code&gt; in NestJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts
// Example: Role Guard
@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const requiredRoles = this.reflector.get&amp;lt;string[]&amp;gt;('roles', context.getHandler());
    return requiredRoles.includes(user.role);
  }
}

// Used like this:
@UseGuards(RolesGuard)
@Roles('admin')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple logic ensures that even if someone sends a forged request, they won't pass unless the role matches.&lt;/p&gt;

&lt;p&gt;🔁 Workspace Validation&lt;br&gt;
We also have workspace-scoped actions. For that, I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;@WorkspaceMember()&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;Logic to confirm the user is part of the workspace they’re acting on&lt;/li&gt;
&lt;li&gt;AuthorizationService with reusable checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧪 Testing&lt;br&gt;
Finally, I used Jest to write tests for key routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can an admin delete a document?&lt;/li&gt;
&lt;li&gt;Can a lawyer access a case from a different workspace? (They shouldn’t)&lt;/li&gt;
&lt;li&gt;Can anyone else invite users to a workspace?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend is UX. Backend is law.&lt;/li&gt;
&lt;li&gt;NestJS makes it easy to build modular, reusable security logic&lt;/li&gt;
&lt;li&gt;Good security is invisible to the user — and obvious to the developer&lt;/li&gt;
&lt;li&gt;I now have a deeper respect for backend checks and how they actually protect users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓ Today’s Question&lt;br&gt;
What’s your approach to securing backend logic in multi-role applications? Do you go with service-based policies, decorators, or custom guards?&lt;/p&gt;

&lt;p&gt;I’d love to hear how others handle authorization at scale.&lt;/p&gt;

&lt;p&gt;Thanks for reading — and see you for Day 22!&lt;/p&gt;

&lt;h1&gt;
  
  
  NestJS #BackendSecurity #RBAC #LearningInPublic #30DaysOfLearning #LuraApp #WebDevJourney
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>backend</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 20 – Building Notification Logic: Keeping Users in the Loop</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Sun, 06 Jul 2025 11:28:45 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-20-building-notification-logic-keeping-users-in-the-loop-5cia</link>
      <guid>https://dev.to/nader_fh/day-20-building-notification-logic-keeping-users-in-the-loop-5cia</guid>
      <description>&lt;p&gt;🧭 Why Notifications Matter&lt;br&gt;
Legal professionals are busy. They don’t want to log in just to check if something changed. So for Lura, our legal case platform, I began implementing a notification system to make sure users get the right information at the right time — whether it's a new document, case, or event.&lt;/p&gt;

&lt;p&gt;It’s not about spamming them — it’s about respecting their time.&lt;/p&gt;

&lt;p&gt;🏗️ System Goals&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Notify users when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new document is added to their case&lt;/li&gt;
&lt;li&gt;A new calendar event is assigned&lt;/li&gt;
&lt;li&gt;A case is created or updated&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let users view unread/read notifications&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allow notifications to be dismissible&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Eventually extend to real-time push or email&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧱 Backend (NestJS + Prisma)&lt;br&gt;
I added a new &lt;code&gt;Notification&lt;/code&gt; model in our Prisma schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prisma
model Notification {
  id          String   @id @default(uuid())
  message     String
  userId      String
  isRead      Boolean  @default(false)
  createdAt   DateTime @default(now())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time a document or event is created, the server creates a new notification assigned to relevant users (typically by role or case ownership).&lt;/p&gt;

&lt;p&gt;In NestJS, I created a reusable &lt;code&gt;NotificationService&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts
@Injectable()
export class NotificationService {
  constructor(private prisma: PrismaService) {}

  async notify(userId: string, message: string) {
    return this.prisma.notification.create({
      data: { userId, message },
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I injected that into controllers like &lt;code&gt;DocumentController&lt;/code&gt; and &lt;code&gt;EventController&lt;/code&gt; to trigger alerts automatically.&lt;/p&gt;

&lt;p&gt;💻 Frontend (Next.js + TailwindCSS)&lt;br&gt;
On the user dashboard, I created a simple notification bell icon. When clicked, it shows a dropdown of the latest alerts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tsx
{notifications.map(note =&amp;gt; (
  &amp;lt;div key={note.id} className="bg-white shadow-sm p-2 rounded-md"&amp;gt;
    &amp;lt;p className="text-sm"&amp;gt;{note.message}&amp;lt;/p&amp;gt;
    &amp;lt;span className="text-xs text-gray-400"&amp;gt;{formatDate(note.createdAt)}&amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
))}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unread notifications are highlighted, and users can mark them as read with one click. I used a small badge icon to show the count of unread alerts.&lt;/p&gt;

&lt;p&gt;🔐 Access Control&lt;br&gt;
Only users assigned to a workspace/case receive its related notifications. The backend checks user roles before inserting or displaying alerts.&lt;/p&gt;

&lt;p&gt;💡 What I Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notifications aren’t just UI features — they’re about clarity and communication.&lt;/li&gt;
&lt;li&gt;Timing and relevance matter more than frequency.&lt;/li&gt;
&lt;li&gt;Prisma made it really easy to store and retrieve alert metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Question&lt;br&gt;
What’s the worst or best notification UX you’ve seen in a real product? Something that made you go, “Wow, this helped”… or “Why did they send me this?”&lt;/p&gt;

&lt;h1&gt;
  
  
  nestjs #nextjs #notificationsystem #uxdesign #backend #prisma #internshipexperience #30DaysOfLearning #LuraApp
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Day 19 – Cleaning Up the Core: Refactoring the Database Schema</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Sat, 05 Jul 2025 15:28:16 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-19-cleaning-up-the-core-refactoring-the-database-schema-1bij</link>
      <guid>https://dev.to/nader_fh/day-19-cleaning-up-the-core-refactoring-the-database-schema-1bij</guid>
      <description>&lt;p&gt;🧠 Context&lt;br&gt;
After nearly three weeks of building features into Lura, our legal case management app, I realized something that many early-stage developers face: your first database schema will rarely be your best.&lt;/p&gt;

&lt;p&gt;Today, I stepped back from building features to refactor and clarify the data relationships between the major entities in our system — Workspaces, Cases, Documents, Users, Tags, and Calendar Events.&lt;/p&gt;

&lt;p&gt;📦 What I Did&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simplified Relationships
At first, we had awkward relationships like:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Case having both workspaceId and a nested workspace reference,&lt;/li&gt;
&lt;li&gt;Document storing redundant workspace references already tied through Case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I cleaned this up using Prisma relations. Now, each document belongs to a case, and the case belongs to a workspace. This means fewer joins, less chance of inconsistency, and clearer logic in queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prisma
model Workspace {
  id        String    @id @default(uuid())
  name      String
  cases     Case[]
}

model Case {
  id           String     @id @default(uuid())
  title        String
  workspace    Workspace  @relation(fields: [workspaceId], references: [id])
  workspaceId  String
  documents    Document[]
}

model Document {
  id       String   @id @default(uuid())
  title    String
  case     Case     @relation(fields: [caseId], references: [id])
  caseId   String
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Improved Naming Conventions&lt;br&gt;
I found names like createdByUser and user_id_fk scattered through my schema. I standardized field names to things like createdById, assignedToId, and made naming consistent across all models.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added Indexes for Performance&lt;br&gt;
Since we often filter by workspaceId, caseId, or tagId, I added indexes in the Prisma schema to optimize query speeds, especially when working with large datasets.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prisma
@@index([workspaceId])
@@index([caseId])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Lessons Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t need to get your schema perfect on Day 1.&lt;/li&gt;
&lt;li&gt;Design clarity = easier maintenance and faster development.&lt;/li&gt;
&lt;li&gt;Refactoring schemas early saves hours later.&lt;/li&gt;
&lt;li&gt;A simple, normalized structure beats clever tricks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔍 Bonus Debug Tip&lt;br&gt;
If you're using Prisma and things stop syncing right after a schema change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma migrate reset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just remember to back up your seed data first!&lt;/p&gt;

&lt;p&gt;❓Question&lt;br&gt;
How often do you audit your data models? Do you prefer to design everything upfront or evolve your schema as the project grows?&lt;/p&gt;

&lt;p&gt;Let me know your approach! Day 20 is going to be exciting — diving into user notifications and communication flows.&lt;/p&gt;

&lt;h1&gt;
  
  
  DatabaseRefactor #Prisma #BackendBestPractices #DevLog #FullstackLearning #SoftwareDesign #InternshipJourney #LuraApp #30DaysOfLearning
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>cleancode</category>
      <category>prisma</category>
    </item>
    <item>
      <title>Day 18 – Building Smarter AI Chatbots with Dify and Prompt Engineering</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Fri, 04 Jul 2025 18:43:35 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-18-building-smarter-ai-chatbots-with-dify-and-prompt-engineering-413k</link>
      <guid>https://dev.to/nader_fh/day-18-building-smarter-ai-chatbots-with-dify-and-prompt-engineering-413k</guid>
      <description>&lt;p&gt;🧠 Today’s Focus&lt;/p&gt;

&lt;p&gt;As Lura evolves into more than just a case and document management platform, I wanted to explore how we can make it feel intelligent — like it’s working with you, not just for you. That led me to deepen my integration of Dify and Ollama, specifically around prompt engineering.&lt;/p&gt;

&lt;p&gt;While I had Dify running earlier in the project, today was about quality — not just functionality.&lt;/p&gt;

&lt;p&gt;🧩 What I Worked On&lt;/p&gt;

&lt;p&gt;1.Refining Prompt Templates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of using a generic prompt like “Summarize this document,” I wrote a more tailored version:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a legal assistant AI inside a document platform. Always summarize in simple language, highlight important names, and suggest next steps for legal actions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;I also tested multiple prompt structures to see how results changed with small adjustments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.Customizing System Instructions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dify allows setting "system messages" that guide how the assistant behaves. I made sure the assistant stays professional, doesn’t hallucinate, and sticks to the workspace’s document context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.PDF Chunking and Indexing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned how Dify chunks large PDF documents before embedding them.&lt;/li&gt;
&lt;li&gt;Tuned the chunk size and overlap to improve answer relevance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4.Testing Real User Scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sample query: “What’s the main point of this contract?”&lt;/li&gt;
&lt;li&gt;I uploaded an actual test contract and watched how the AI summarized it in 3 lines, perfectly highlighting the client name and conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔧 Useful Code/Setup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# My Dify docker-compose.yaml snippet
  dify:
    image: langgenius/dify
    environment:
      - MODEL_PROVIDER=ollama
      - SYSTEM_PROMPT="You are a legal assistant..."
    volumes:
      - ./data:/app/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Sample Prompt Template in UI
{
  "prompt": "Summarize this legal document in plain language. Highlight any deadlines or responsibilities.",
  "context": "Document file content here..."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt engineering is UX for AI. How you phrase things matters a lot.&lt;/li&gt;
&lt;li&gt;Even “dumb” chatbots can become useful with thoughtful design.&lt;/li&gt;
&lt;li&gt;Working with lawyers? Be precise. AI must never invent or exaggerate.&lt;/li&gt;
&lt;li&gt;Keeping tone and context on-brand is just as important as accuracy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Question&lt;br&gt;
Have you ever tried building your own assistant — even something simple? What did you wish you knew before starting?&lt;/p&gt;

&lt;p&gt;On to Day 19. 👨‍💻💬&lt;/p&gt;

&lt;h1&gt;
  
  
  AI #Ollama #ChatbotDevelopment #LegalTech #Dify #PromptEngineering #JavaScript #InternshipJourney #LuraApp #30DaysOfCode
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>ai</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>Day 17 – Securing Files with Role-Based Permissions</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Thu, 03 Jul 2025 16:06:02 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-17-securing-files-with-role-based-permissions-3k4p</link>
      <guid>https://dev.to/nader_fh/day-17-securing-files-with-role-based-permissions-3k4p</guid>
      <description>&lt;p&gt;📂 "Oops, I deleted the wrong file..."&lt;/p&gt;

&lt;p&gt;That’s a nightmare in any app — but in legal software? It’s a lawsuit waiting to happen.&lt;/p&gt;

&lt;p&gt;So on Day 17 of my internship learning journey, I focused on a vital but often overlooked problem: making sure only authorized users can delete documents.&lt;/p&gt;

&lt;p&gt;🧱 Background&lt;br&gt;
I previously built a file upload feature tied to legal cases. But until now, anyone could delete documents.&lt;/p&gt;

&lt;p&gt;In reality, a junior lawyer shouldn’t be able to remove court evidence by mistake. So, I implemented Role-Based Access Control (RBAC) specifically for file deletion.&lt;/p&gt;

&lt;p&gt;🔐 RBAC Rules for Document Handling&lt;br&gt;
Role              Upload    View    Delete&lt;br&gt;
Lawyer              ✅          ✅      ❌&lt;br&gt;
Admin               ✅          ✅      ✅&lt;br&gt;
Super Admin     ✅          ✅      ✅&lt;/p&gt;

&lt;p&gt;These rules were enforced in both backend and frontend.&lt;/p&gt;

&lt;p&gt;⚙️ Backend Implementation (NestJS + Prisma)&lt;br&gt;
I updated the document deletion route in NestJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@UseGuards(AuthGuard, RolesGuard)
@Roles('ADMIN', 'SUPER_ADMIN')
@Delete('/documents/:id')
async deleteDoc(@Param('id') id: string) {
  return this.documentService.remove(id);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures only authorized users can trigger deletion, even if they try via tools like Postman.&lt;/p&gt;

&lt;p&gt;💻 Frontend Guards (Next.js)&lt;br&gt;
In the file list UI, I used useUser() to conditionally show the delete button only to eligible roles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN' ? (
  &amp;lt;button onClick={() =&amp;gt; deleteFile(file.id)}&amp;gt;🗑️ Delete&amp;lt;/button&amp;gt;
) : null}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if someone inspects the page and reveals the button, the backend guard blocks them.&lt;/p&gt;

&lt;p&gt;🧠 What I Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security isn’t just about code — it’s about UI decisions, too.&lt;/li&gt;
&lt;li&gt;People trust file systems. You only notice it when things break.&lt;/li&gt;
&lt;li&gt;NestJS guards + frontend conditional rendering = powerful security combo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Extra UX Touches&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show a confirmation modal before deletion.&lt;/li&gt;
&lt;li&gt;Use toast notifications for success/error feedback.&lt;/li&gt;
&lt;li&gt;Added metadata (who deleted what, and when).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Discussion Question&lt;br&gt;
Have you ever had to roll back a user’s accidental delete?&lt;br&gt;
What safeguards do you build around sensitive actions?&lt;/p&gt;

&lt;p&gt;Let me know — and see you tomorrow for Day 18!&lt;/p&gt;

&lt;h1&gt;
  
  
  RBAC #LearningInPublic #SecurityByDesign #LuraApp #InternshipDevLog
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>security</category>
      <category>nestjs</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Day 16 – Building Calendar Events That Actually Matter</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Wed, 02 Jul 2025 15:01:18 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-16-building-calendar-events-that-actually-matter-1hhm</link>
      <guid>https://dev.to/nader_fh/day-16-building-calendar-events-that-actually-matter-1hhm</guid>
      <description>&lt;p&gt;If you told me at the start of this internship that I’d be stressing over date pickers, I would’ve laughed.&lt;/p&gt;

&lt;p&gt;But here we are. On Day 16, I built the calendar event management system inside Lura — and it’s one of the most human features we’ve touched so far.&lt;/p&gt;

&lt;p&gt;🗓️ Why Calendars Matter in Legal Work&lt;br&gt;
Lawyers deal with time-sensitive responsibilities. One missed court date, one forgotten contract review — it’s chaos. So for Lura, we had to build a calendar system that didn’t just store events, but respected context.&lt;/p&gt;

&lt;p&gt;We didn’t want a global calendar. We wanted event timelines scoped to cases.&lt;/p&gt;

&lt;p&gt;⚙️ How It Works&lt;br&gt;
Each event has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;li&gt;Start/End DateTime&lt;/li&gt;
&lt;li&gt;Related Case ID&lt;/li&gt;
&lt;li&gt;CreatedBy &amp;amp; updatedBy&lt;/li&gt;
&lt;li&gt;Visibility based on user role&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the backend, I used Prisma to define the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model Event {
  id          String   @id @default(uuid())
  title       String
  description String?
  startTime   DateTime
  endTime     DateTime
  caseId      String
  createdBy   String
  updatedAt   DateTime @updatedAt
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The NestJS controller validates the input and checks role permissions — only Admins and Lawyers can create/edit, while Super Admins have global access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@UseGuards(AuthGuard, RolesGuard)
@Roles('ADMIN', 'LAWYER')
@Post('/cases/:caseId/events')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💻 Frontend: The Form &amp;amp; List&lt;br&gt;
I used Next.js with TailwindCSS to build a small, responsive form:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Date pickers for start/end&lt;/li&gt;
&lt;li&gt;Character limits for titles&lt;/li&gt;
&lt;li&gt;Real-time form validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Events appear in a clean list under each case view. I kept it simple, but clear — readable datetime, case context, and edit/delete buttons (based on role).&lt;/p&gt;

&lt;p&gt;🧠 Things That Surprised Me&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Date logic gets tricky fast – I had to handle overlapping events and timezone issues even for internal use.&lt;/li&gt;
&lt;li&gt;Empty states matter – If a case has no events, that should be obvious and friendly, not just blank.&lt;/li&gt;
&lt;li&gt;People really trust their calendars – this reminded me how much power (and responsibility) we have when storing others' plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Key Lessons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always connect calendar features to the real world — lawyers don’t want clutter, they want clarity.&lt;/li&gt;
&lt;li&gt;Backend validation is just as important as UI — especially for date logic.&lt;/li&gt;
&lt;li&gt;Don’t underestimate “boring” UX details. Smart defaults go a long way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓Question for You:&lt;br&gt;
When you build event or calendar features, do you prefer a dedicated calendar UI — or filtered event lists?&lt;/p&gt;

&lt;p&gt;Let me know how you approach these tiny-but-vital features.&lt;/p&gt;

&lt;p&gt;See you on Day 17 👋&lt;/p&gt;

&lt;h1&gt;
  
  
  calendarEvents #UXMatters #LegalSoftware #LuraApp #LearningInPublic #DevBlog
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>learning</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Day 15 – Turning a Plain File List into a Real User Experience</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Mon, 30 Jun 2025 17:45:00 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-15-turning-a-plain-file-list-into-a-real-user-experience-58mj</link>
      <guid>https://dev.to/nader_fh/day-15-turning-a-plain-file-list-into-a-real-user-experience-58mj</guid>
      <description>&lt;p&gt;Let me be honest — today’s task wasn’t particularly glamorous.&lt;/p&gt;

&lt;p&gt;No AI models, no fancy dashboards. I spent the day working on how documents appear after upload inside Lura. Basically: I took a raw, functional file list… and made it not suck.&lt;/p&gt;

&lt;p&gt;🧩 Why This Mattered&lt;br&gt;
Lura is a lawyer management system. That means our users — mostly legal professionals — live inside cases and documents. They don’t care about our database schema or component trees. They care about clarity.&lt;/p&gt;

&lt;p&gt;Before today, here’s what document display looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- 1248dd9_contract.pdf  
- meeting_notes_final_final_2.docx  
- IMG_23423.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was it. Not great.&lt;/p&gt;

&lt;p&gt;⚙️ What I Did&lt;br&gt;
I redesigned the component to show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File type icon (PDFs, Word docs, images, etc.)&lt;/li&gt;
&lt;li&gt;Human-readable file sizes using pretty-bytes&lt;/li&gt;
&lt;li&gt;Timestamps like “uploaded 3 hours ago”&lt;/li&gt;
&lt;li&gt;Image previews on hover (for supported types)&lt;/li&gt;
&lt;li&gt;Conditional delete button based on user role&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the frontend, I used &lt;code&gt;useRouter()&lt;/code&gt; and &lt;code&gt;useUser()&lt;/code&gt; to grab the active user’s role and decide what actions they could perform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{canDelete &amp;amp;&amp;amp; (
  &amp;lt;button onClick={() =&amp;gt; deleteFile(file.id)}&amp;gt;🗑️ Delete&amp;lt;/button&amp;gt;
)}

&amp;lt;span&amp;gt;{prettyBytes(file.size)}&amp;lt;/span&amp;gt;
&amp;lt;span&amp;gt;{dayjs(file.createdAt).fromNow()}&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔧 Backend Cleanup&lt;br&gt;
In NestJS, I made sure each upload stored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File name&lt;/li&gt;
&lt;li&gt;Size&lt;/li&gt;
&lt;li&gt;MIME type&lt;/li&gt;
&lt;li&gt;Case &amp;amp; Workspace linkage&lt;/li&gt;
&lt;li&gt;Uploading user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I cleaned up the file retrieval route to send everything needed to the UI without extra processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return await this.prisma.document.findMany({
  where: { caseId },
  include: { uploadedBy: true },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Reflections&lt;br&gt;
This wasn’t a big, technical challenge. But I think it’s one of the most important things I’ve done so far.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because it reminded me that good software is about humans. Not code. Not complexity. People.&lt;/p&gt;

&lt;p&gt;Our users don’t care if the backend is elegant. They care if they can see their contract at a glance. That’s it.&lt;/p&gt;

&lt;p&gt;And now? They can.&lt;/p&gt;

&lt;p&gt;❓Question:&lt;br&gt;
How do you turn “boring” features into something thoughtful in your projects?&lt;/p&gt;

&lt;p&gt;Would love to hear about how others think about UX in places nobody notices — until it’s done wrong.&lt;/p&gt;

&lt;p&gt;See you tomorrow 👋&lt;/p&gt;

&lt;h1&gt;
  
  
  FullstackDev #NestJS #NextJS #LegalTech #LuraApp #LearningInPublic #UXDesign
&lt;/h1&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>ux</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>📝 Blog Post – Day 14: Implementing Role-Based Access Control (RBAC)</title>
      <dc:creator>Nader Fkih Hassen</dc:creator>
      <pubDate>Sun, 29 Jun 2025 17:40:04 +0000</pubDate>
      <link>https://dev.to/nader_fh/day-14-role-based-access-control-rbac-2d3o</link>
      <guid>https://dev.to/nader_fh/day-14-role-based-access-control-rbac-2d3o</guid>
      <description>&lt;p&gt;Today’s focus in the Lura project was on Role-Based Access Control (RBAC) — a concept that ensures users only have access to what they’re supposed to see or do.&lt;/p&gt;

&lt;p&gt;🔐 Why RBAC Matters&lt;br&gt;
In a legal platform like Lura, different users (lawyers, admins, super admins) need clearly defined responsibilities and permissions. You can’t allow a regular lawyer to delete documents, or a new user to modify system settings. RBAC solves that by assigning roles and mapping them to actions.&lt;/p&gt;

&lt;p&gt;🧩 Goals of Today’s Feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clearly define 3 user roles: Lawyer, Admin, Super Admin&lt;/li&gt;
&lt;li&gt;Secure sensitive API routes (delete, update, create)&lt;/li&gt;
&lt;li&gt;Control visibility of buttons and pages in UI&lt;/li&gt;
&lt;li&gt;Prevent role spoofing by enforcing checks server-side&lt;/li&gt;
&lt;li&gt;Ensure new users are onboarded with appropriate roles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ How I Built It&lt;br&gt;
📦 Backend (NestJS + Prisma)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I used NestJS Guards and a custom @Roles() decorator to protect controller routes.&lt;/li&gt;
&lt;li&gt;User roles were stored in the database using Prisma’s user model.&lt;/li&gt;
&lt;li&gt;I created middleware that intercepts requests and checks JWT tokens for valid roles.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@UseGuards(AuthGuard, RolesGuard)
@Roles('admin')
@Delete('/document/:id')
removeFile() { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;💻 Frontend (Next.js + Context)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I pulled the logged-in user’s role from the session context.&lt;/li&gt;
&lt;li&gt;Using conditional rendering, I hid buttons and restricted actions for lower roles.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{user.role === 'admin' &amp;amp;&amp;amp; &amp;lt;DeleteButton /&amp;gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔒 Extra Layer of Security&lt;br&gt;
You can’t trust frontend checks alone. That’s why every sensitive route also has backend protection — ensuring only valid roles can trigger dangerous actions like deletions or workspace edits.&lt;/p&gt;

&lt;p&gt;I also created a helper function to easily assign roles during registration based on invitation logic (admin invites lawyer, super admin creates admins, etc.).&lt;/p&gt;

&lt;p&gt;✅ Key Lessons &amp;amp; Takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RBAC creates safer and more maintainable software.&lt;/li&gt;
&lt;li&gt;It prevents accidental misuse and enforces real-world policies.&lt;/li&gt;
&lt;li&gt;NestJS makes backend security very modular with guards and decorators.&lt;/li&gt;
&lt;li&gt;UI must align with backend logic — security isn’t only about APIs.&lt;/li&gt;
&lt;li&gt;Planning your access model early makes future scaling easier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❓ Question:&lt;br&gt;
How do you handle permissions in your web apps?&lt;br&gt;
Would you go with RBAC, ACL (Access Control Lists), or something more dynamic like policy-based access?&lt;/p&gt;

</description>
      <category>30daysoflearning</category>
      <category>webdev</category>
      <category>devjournal</category>
      <category>rbac</category>
    </item>
  </channel>
</rss>
